尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
第七篇:《初识 net/http:构建第一个 RESTful API》
掌握了 Go 的基础语法和并发模型后我们正式进入 Web 开发领域。Go 的标准库 net/http 已经足够强大无需第三方框架就能构建一个完整的 RESTful API 服务。本文从 http.Handler 接口和 http.ServeMux 路由器讲起深入讲解如何编写 Handler 处理 HTTP 请求、如何读取请求参数和请求体、如何返回 JSON 响应以及如何用闭包实现中间件。最后通过一个完整的“图书管理”CRUD API 实战帮你建立 Go Web 开发的基础认知。一、net/http 核心接口http.Handlernet/http 包的核心是 http.Handler 接口typeHandlerinterface{ServeHTTP(w http.ResponseWriter,r*http.Request)}任何实现了 ServeHTTP 方法的类型都可以作为 HTTP 处理器。1.1 函数式 Handlerhttp.HandlerFunchttp.HandlerFunc 是一个函数类型它实现了 http.Handler 接口允许将普通函数直接转换为 Handlerpackagemainimport(fmtnet/http)// 普通函数作为 HandlerfunchelloHandler(w http.ResponseWriter,r*http.Request){fmt.Fprintf(w,Hello, World!)}funcmain(){// http.HandlerFunc 将函数转换为 Handlerhttp.HandleFunc(/hello,helloHandler)// 启动服务器http.ListenAndServe(:8080,nil)}访问 http://localhost:8080/hello即可看到 Hello, World!。1.2 结构体 Handler面向对象风格typeGreetingHandlerstruct{Namestring}func(h*GreetingHandler)ServeHTTP(w http.ResponseWriter,r*http.Request){fmt.Fprintf(w,Greeting from %s,h.Name)}funcmain(){handler:GreetingHandler{Name:MyApp}http.Handle(/greeting,handler)http.ListenAndServe(:8080,nil)}二、处理 HTTP 请求2.1 读取 URL 参数Query String使用 r.URL.Query() 读取查询参数funcgetUserHandler(w http.ResponseWriter,r*http.Request){// 获取查询参数query:r.URL.Query()name:query.Get(name)// /user?nameAliceage:query.Get(age)// /user?nameAliceage30fmt.Fprintf(w,name: %s, age: %s,name,age)}2.2 读取路径参数Path ParametersGo 标准库不直接支持路由参数如 /user/123需要自行解析路径或使用 http.ServeMux 的路径匹配模式。更常用的是直接使用 r.URL.Path 解析或者后续章节引入 Gin 框架来处理更复杂的路由。funcuserHandler(w http.ResponseWriter,r*http.Request){// 解析路径/users/123path:r.URL.Path// 简单解析parts:strings.Split(path,/)iflen(parts)3{id:parts[2]// 123fmt.Fprintf(w,User ID: %s,id)}}2.3 读取请求体POST / PUT对于 POST/PUT 请求需要从请求体中读取数据import(encoding/jsonionet/http)typeUserstruct{Namestringjson:nameAgeintjson:age}funccreateUserHandler(w http.ResponseWriter,r*http.Request){// 只允许 POST 方法ifr.Method!http.MethodPost{http.Error(w,Method not allowed,http.StatusMethodNotAllowed)return}// 读取请求体body,err:io.ReadAll(r.Body)iferr!nil{http.Error(w,读取请求体失败,http.StatusBadRequest)return}deferr.Body.Close()// 解析 JSONvaruser Useriferr:json.Unmarshal(body,user);err!nil{http.Error(w,JSON 解析失败,http.StatusBadRequest)return}fmt.Fprintf(w,接收到用户: %s, 年龄: %d,user.Name,user.Age)}三、返回 HTTP 响应3.1 返回 JSON 响应使用 json.NewEncoder 可以方便地返回 JSON 格式的响应typeResponsestruct{Codeintjson:codeMessagestringjson:messageDatainterface{}json:data,omitempty}funcapiHandler(w http.ResponseWriter,r*http.Request){// 设置响应头w.Header().Set(Content-Type,application/json)// 构造响应数据resp:Response{Code:200,Message:success,Data:map[string]string{status:ok},}// 返回 JSONw.WriteHeader(http.StatusOK)json.NewEncoder(w).Encode(resp)}3.2 设置状态码和响应头funchandler(w http.ResponseWriter,r*http.Request){// 设置响应头w.Header().Set(X-Custom-Header,my-value)w.Header().Set(Content-Type,application/json)// 设置状态码w.WriteHeader(http.StatusCreated)// 201// 写入响应体w.Write([]byte({status:ok}))}四、中间件Middleware中间件是一个高阶函数它接收一个 http.Handler 并返回一个新的 http.Handler可以在请求处理前后执行逻辑。net/http 标准库中没有直接定义中间件模式但通过闭包可以非常方便地实现。// 日志中间件funcloggerMiddleware(next http.Handler)http.Handler{returnhttp.HandlerFunc(func(w http.ResponseWriter,r*http.Request){fmt.Printf([%s] %s %s\n,time.Now().Format(2006-01-02 15:04:05),r.Method,r.URL.Path)next.ServeHTTP(w,r)// 调用下一个处理器})}// Recovery 中间件捕获 panicfuncrecoveryMiddleware(next http.Handler)http.Handler{returnhttp.HandlerFunc(func(w http.ResponseWriter,r*http.Request){deferfunc(){iferr:recover();err!nil{log.Printf(panic 恢复: %v,err)http.Error(w,服务器内部错误,http.StatusInternalServerError)}}()next.ServeHTTP(w,r)})}// 应用中间件funcmain(){mux:http.NewServeMux()mux.HandleFunc(/,helloHandler)// 中间件链handler:recoveryMiddleware(loggerMiddleware(mux))http.ListenAndServe(:8080,handler)}五、实战图书管理 CRUD API纯标准库下面是一个完整的图书管理 API包含创建、查询、更新、删除操作全部基于标准库实现packagemainimport(encoding/jsonfmtnet/httpsync)// 图书模型typeBookstruct{IDstringjson:idTitlestringjson:titleAuthorstringjson:authorPriceintjson:price}// 图书仓库typeBookStorestruct{mu sync.RWMutex booksmap[string]Book}funcNewBookStore()*BookStore{returnBookStore{books:make(map[string]Book),}}func(s*BookStore)Create(book Book){s.mu.Lock()defers.mu.Unlock()s.books[book.ID]book}func(s*BookStore)Get(idstring)(Book,bool){s.mu.RLock()defers.mu.RUnlock()book,ok:s.books[id]returnbook,ok}func(s*BookStore)GetAll()[]Book{s.mu.RLock()defers.mu.RUnlock()books:make([]Book,0,len(s.books))for_,book:ranges.books{booksappend(books,book)}returnbooks}func(s*BookStore)Update(idstring,book Book)bool{s.mu.Lock()defers.mu.Unlock()if_,ok:s.books[id];!ok{returnfalse}book.IDid s.books[id]bookreturntrue}func(s*BookStore)Delete(idstring)bool{s.mu.Lock()defers.mu.Unlock()if_,ok:s.books[id];!ok{returnfalse}delete(s.books,id)returntrue}// ---- HTTP Handlers ----varstoreNewBookStore()funcrespondJSON(w http.ResponseWriter,statusint,datainterface{}){w.Header().Set(Content-Type,application/json)w.WriteHeader(status)json.NewEncoder(w).Encode(data)}funcgetAllBooks(w http.ResponseWriter,r*http.Request){books:store.GetAll()respondJSON(w,http.StatusOK,books)}funcgetBookByID(w http.ResponseWriter,r*http.Request){// 简单路径解析/books/123id:r.URL.Path[len(/books/):]ifid{http.Error(w,id 不能为空,http.StatusBadRequest)return}book,ok:store.Get(id)if!ok{http.Error(w,图书不存在,http.StatusNotFound)return}respondJSON(w,http.StatusOK,book)}funccreateBook(w http.ResponseWriter,r*http.Request){ifr.Method!http.MethodPost{http.Error(w,Method not allowed,http.StatusMethodNotAllowed)return}varbook Bookiferr:json.NewDecoder(r.Body).Decode(book);err!nil{http.Error(w,JSON 解析失败,http.StatusBadRequest)return}deferr.Body.Close()ifbook.ID{http.Error(w,id 不能为空,http.StatusBadRequest)return}store.Create(book)respondJSON(w,http.StatusCreated,book)}funcupdateBook(w http.ResponseWriter,r*http.Request){ifr.Method!http.MethodPut{http.Error(w,Method not allowed,http.StatusMethodNotAllowed)return}id:r.URL.Path[len(/books/):]ifid{http.Error(w,id 不能为空,http.StatusBadRequest)return}varbook Bookiferr:json.NewDecoder(r.Body).Decode(book);err!nil{http.Error(w,JSON 解析失败,http.StatusBadRequest)return}deferr.Body.Close()if!store.Update(id,book){http.Error(w,图书不存在,http.StatusNotFound)return}respondJSON(w,http.StatusOK,book)}funcdeleteBook(w http.ResponseWriter,r*http.Request){ifr.Method!http.MethodDelete{http.Error(w,Method not allowed,http.StatusMethodNotAllowed)return}id:r.URL.Path[len(/books/):]ifid{http.Error(w,id 不能为空,http.StatusBadRequest)return}if!store.Delete(id){http.Error(w,图书不存在,http.StatusNotFound)return}w.WriteHeader(http.StatusNoContent)}funcmain(){// 初始化一些示例数据store.Create(Book{ID:1,Title:Go 入门,Author:张三,Price:59})store.Create(Book{ID:2,Title:微服务架构,Author:李四,Price:89})// 路由http.HandleFunc(/books,func(w http.ResponseWriter,r*http.Request){switchr.Method{casehttp.MethodGet:getAllBooks(w,r)casehttp.MethodPost:createBook(w,r)default:http.Error(w,Method not allowed,http.StatusMethodNotAllowed)}})http.HandleFunc(/books/,func(w http.ResponseWriter,r*http.Request){switchr.Method{casehttp.MethodGet:getBookByID(w,r)casehttp.MethodPut:updateBook(w,r)casehttp.MethodDelete:deleteBook(w,r)default:http.Error(w,Method not allowed,http.StatusMethodNotAllowed)}})fmt.Println(服务器启动在 :8080)http.ListenAndServe(:8080,nil)}测试 API# 获取所有图书curlhttp://localhost:8080/books# 创建图书curl-XPOST http://localhost:8080/books-HContent-Type: application/json-d{id:3,title:Go 并发, author:王五, price:69}# 获取单本图书curlhttp://localhost:8080/books/1# 更新图书curl-XPUT http://localhost:8080/books/1-HContent-Type: application/json-d{title:Go 入门第二版, author:张三, price:79}# 删除图书curl-XDELETE http://localhost:8080/books/1六、小结http.Handler核心接口ServeHTTP(w http.ResponseWriter, r *http.Request) 是 Go Web 的起点。路由http.ServeMux 是标准库的路由器支持路径匹配。请求处理r.URL.Query() 读取查询参数io.ReadAll(r.Body) 读取请求体json.Unmarshal 解析 JSON。响应返回w.Header().Set() 设置响应头w.WriteHeader() 设置状态码json.NewEncoder(w).Encode() 返回 JSON。中间件使用闭包实现接收 http.Handler 返回 http.Handler可以实现日志、鉴权、恢复等功能。
RELATED

相关推荐

本地 AI 数字员工 OpenClaw 实操,图形化安装规避各类部署报错(含安装包)

本地 AI 数字员工 OpenClaw 实操,图形化安装规避各类部署报错(含安装包)

Windows/macOS OpenClaw v2.7.9 安装实操|整合包简化本地 AI 智能体搭建 适配系统:Windows10/11 64 位、macOS 12 及以上 当前版本:v2.7.9(虾壳云整合版本) 核心亮点 图形化交互部署流程,不需要命令行操…

📅 2026/9/18 23:19:34
大模型技术全景与职业发展指南

大模型技术全景与职业发展指南

1. 大模型行业全景与职业机遇 大模型技术正在重塑全球科技产业格局,从2023年ChatGPT引爆市场至今,相关岗位需求呈现指数级增长。根据领英最新数据,大模型相关职位发布量年增长率达到470%,平均薪资较传统IT岗位高出35-60%。这个领域…

📅 2026/7/27 10:11:16
成交量优化 同花顺期货通指标

成交量优化 同花顺期货通指标

今天给大家带来是一款同花顺期货通指标,并且已经上架到同花顺期货通的指标广场上了。喜欢的朋友可以去指标广场安装试用!!友情提示:(指标只是辅助,不作建议)拼多多店铺:指标公式编写…

📅 2026/8/3 16:33:13
MORE NEWS

更多资讯

📰

用XinServer实现项目进度自动化管理:从任务编排到CI/CD联动

开头:从一次差点翻车的进度会说起上季度我们团队负责一个边缘业务系统的升级,排期只有六周,需求却拆出了四十多个子任务。当时我心里其实没底,因为团队里一半人同时要处理线上问题,另一半人对新业务逻辑不熟。开进度会…

📰

StarRocks 数学函数 ln / dlog1 / log:自然对数计算的语法、边界行为与向量化实现解析

StarRocks 数学函数 ln / dlog1 / log:自然对数计算的语法、边界行为与向量化实现解析 【免费下载链接】starrocks The worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly a…

📰

系统提示词泄露的工程读法:结构拆解与分层实践

第一次看到system_prompts_leaks这类仓库刷屏的时候,我的第一反应不是兴奋,而是有点无奈——因为对做过线上大模型应用的人来说,系统提示词(system prompts)被扒出来这件事,早就不是什么新鲜事了&#xff0…

📰

Claude Code Harness Codex Companion Review:让 AI 互审 AI 的分步教程

Claude Code Harness Codex Companion Review:让 AI 互审 AI 的分步教程 【免费下载链接】claude-code-harness Claude Code Dedicated Development Harness - Achieving High-Quality Development Through an Autonomous Plan→Work→Review Cycle 项目地址: htt…

📰

mhc_post 算子代码级正确性证明:从 mHC 论文公式到 PyTorch 参考实现与 AscendC NPU Kernel 的全链路推导

mhc_post 算子代码级正确性证明:从 mHC 论文公式到 PyTorch 参考实现与 AscendC NPU Kernel 的全链路推导 【免费下载链接】ops-transformer 本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。 项目地址: https://gitcode.com/c…

📰

亚马逊云科技智能投标 Agent 跑 Agent Harness 长任务,Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬