如何使用Golang构建基础的REST API_Golang REST API接口设计与实现方法
发布时间 - 2026-01-03 00:00:00 点击率:次net/http 可直接启动轻量 REST 服务:用 http.ListenAndServe 启动,http.HandleFunc 注册严格路径路由,handler 中需手动读取并校验 req.Body、设置 Content-Type 为 application/json;注意 req.Body 只能读一次、ServeMux 前缀匹配陷阱及显式处理 404。
用 net/http 启动最简 REST 服务,别急着上框架
Go 自带的 net/http 足够支撑大多数基础 API 场景,启动快、依赖少、逻辑透明。过度依赖 gin 或 echo 容易掩盖路由分发、中间件执行顺序、错误传播路径等关键细节。
- 直接调用
http.ListenAndServe(":8080", nil)即可启动服务,nil表示使用默认的http.DefaultServeMux - 用
http.HandleFunc("/users", handlerFunc)注册路由,注意路径末尾不自动匹配子路径(/users≠/users/123) - 所有 handler 函数签名必须是
func(http.ResponseWriter, *http.Request),返回值不能传 error,需手动写入响应 - 别在 handler 里 panic——Go 的 HTTP server 不会 recover,一次 panic 就整条连接挂掉
解析 JSON 请求体时,json.Unmarshal 前必须先读取 req.Body
常见错误是直接对 req.Body 多次调用 json.Unmarshal,结果第二次开始全为零值。因为 req.Body 是单向流,读完即空。
- 务必用
io.ReadAll(req.Body)一次性读出全部字节,再传给json.Unmarshal - 记得在读取前检查
req.Method和req.Header.Get("Content-Type"),避免对GET请求尝试读 body - 若需复用 body(如日志或鉴权),应提前用
req.Body = io.NopCloser(bytes.NewBuffer(data))包装回io.ReadCloser
data, err := io.ReadAll(req.Body)
if err != nil {
http.Error(w, "bad request body", http.StatusBadRequest)
return
}
var u User
if err := json.Unmarshal(data, &u); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
返回 JSON 响应时,Content-Type 必须显式设置为 application/json; charset=utf-8
不设 header 导致前端 fetch().json() 报错 “Unexpected token”,浏览器可能按 text/html 解析,中文变乱码。
- 用
w.Header().Set("Content-Type", "application/json; charset=utf-8")显式声明 - 避免用
fmt.Fprintf直接输出 JSON 字符串——它不处理转义、不控制精度、不兼容结构体字段 tag(如json:"name,omitempty") - 用
json.NewEncoder(w).Encode(v)替代json.Marshal+Write,前者支持流式编码,内存更友好
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if err := json.NewEncoder(w).Encode(map[string]string{"status": "ok"}); err != nil {
http.Error(w, "encode error", http.StatusInternalServerError)
}
路由设计要避开 http.ServeMux 的路径匹配陷阱
http.ServeMux 只做前缀匹配,且不区分 trailing slash,/api 会意外匹配到 /ap 并交给同一 handler,但你没实现子路径逻辑。
i/users
立即学习“go语言免费学习笔记(深入)”;
- 注册路由时严格写全路径:
http.HandleFunc("/api/users", listUsers),不要只写/api - 需要层级路由,自己做路径分割:
strings.Split(strings.TrimPrefix(req.URL.Path, "/api"), "/") - 404 处理不能依赖框架自动 fallback——
http.NotFound(w, req)必须显式调用,否则返回空 200 - 如果 URL 含查询参数(如
/users?limit=10),用req.URL.Query().Get("limit")获取,别手撕req.URL.RawQuery
req.Body 只能读一次、http.ServeMux 不校验路径结尾、JSON 编码器和字符串拼接混用这些细节。写完一个 handler,先 curl 测一遍 status code 和 Content-Type,比跑通单元测试还管用。
# html
# js
# 前端
# json
# go
# golang
# 编码
# 浏览器
# app
# 字节
# usb
# curl
# ai
# 路由
# 中间件
# gin
# echo
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
郑州企业网站制作公司,郑州招聘网站有哪些?
Laravel如何保护应用免受CSRF攻击?(原理和示例)
Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
Laravel如何优化应用性能?(缓存和优化命令)
作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】
如何选择可靠的免备案建站服务器?
百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧
JS碰撞运动实现方法详解
如何自定义建站之星网站的导航菜单样式?
微信小程序 require机制详解及实例代码
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
如何生成腾讯云建站专用兑换码?
深圳网站制作培训,深圳哪些招聘网站比较好?
Android okhttputils现在进度显示实例代码
如何在景安云服务器上绑定域名并配置虚拟主机?
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
微信小程序制作网站有哪些,微信小程序需要做网站吗?
手机软键盘弹出时影响布局的解决方法
如何快速搭建FTP站点实现文件共享?
如何破解联通资金短缺导致的基站建设难题?
Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
Laravel中的Facade(门面)到底是什么原理
如何在IIS7中新建站点?详细步骤解析
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用
如何在万网主机上快速搭建网站?
node.js报错:Cannot find module 'ejs'的解决办法
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
如何在橙子建站上传落地页?操作指南详解
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
南京网站制作费用,南京远驱官方网站?
网站图片在线制作软件,怎么在图片上做链接?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
三星、SK海力士获美批准:可向中国出口芯片制造设备
Python制作简易注册登录系统
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
php 三元运算符实例详细介绍
香港服务器如何优化才能显著提升网站加载速度?
JavaScript数据类型有哪些_如何准确判断一个变量的类型
iOS验证手机号的正则表达式
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
iOS正则表达式验证手机号、邮箱、身份证号等
魔毅自助建站系统:模板定制与SEO优化一键生成指南

