Go 起个 HTTP 服务三行代码,能上线还差这五件事

Go 起个 HTTP 服务三行代码,能上线还差这五件事

一、原理:一个结构体撑起整个服务

Go 的 net/http 包用 http.Server 结构体封装服务器配置与状态:监听地址与端口,收到请求后分发给对应处理器,处理器生成响应返回。最简形式是两句话——用 http.HandleFunc 把路径绑到函数,用 http.ListenAndServe 监听端口、使用默认多路复用器。

处理器函数拿到两个东西:http.ResponseWriter 用来写响应,*http.Request 用来读请求(方法、查询参数、请求头、请求体)。所有 Web 逻辑都围绕这两个对象展开。

二、路由:标准库够不够

原文的判断很直接:标准库提供基本路由,通过 HandleFunc 把不同路径映射到不同处理器,够用;但复杂应用通常会用第三方路由库,例如 gorilla/mux,支持路径变量与按方法限制(只有 GET 才触发某个处理器)。

需求标准库第三方路由
固定路径够用够用
路径带变量需自己解析原生支持
按方法区分需在处理器内判断声明式配置

三、静态文件与中间件

静态文件:用 http.FileServer 指向目录,再配合 http.StripPrefix 去掉路径前缀,请求才能正确定位到文件。少了去前缀这一步,最常见的现象就是 404。

中间件:在请求到达最终处理器前后执行的函数,用于日志、鉴权这类通用逻辑。原文的日志中间件做得很朴素——进函数打一行开始,调用下一个处理器,出函数打一行结束。但它体现了中间件的本质:接收一个处理器,返回一个包装后的处理器,可以层层套。

四、数据库:连接要开一次,查询要记得关

与数据库交互的典型写法是:启动时打开一次连接(sql.Open),用 defer 在退出时关闭;处理器里执行查询,用 defer 关闭结果集,逐行扫描到变量中。

两个 defer 别省:连接不关会泄漏连接,结果集不关会占住连接。这两个问题在低并发下几乎看不出来,上线后才会集中爆发。

原文示例里把查询错误直接写进响应返回给客户端,这在调试阶段方便,生产环境要改——错误信息会泄露表结构。

五、性能与安全:原文给的两组建议

性能三招:连接池管理数据库连接,减少创建销毁开销;对频繁访问的数据加缓存(内存缓存或分布式缓存);耗时操作用协程异步处理,避免阻塞主流程。

安全三条:严格校验用户输入,防注入与 XSS;用 HTTPS 加密传输,通过 http.ListenAndServeTLS 启动加密服务;设置 CSP 响应头,限制页面可加载的资源来源。

六、日志、监控与上线自查

日志记录请求信息与错误信息,监控关注 CPU、内存、响应时间这类指标。原文提到的组合是日志库加监控工具。这块经常被放到"以后再说",但恰恰是出事时唯一能还原现场的东西。

把上面几块串起来,上线前自查这五条:

  1. 路由是否需要路径变量与按方法限制?
  2. 静态目录是否配了去前缀?
  3. 日志与鉴权是否已做成中间件,而不是散落在每个处理器里?
  4. 数据库连接与结果集是否都 defer 关闭?
  5. 是否启用了 TLS,错误信息是否还对客户端暴露?

Go 让"跑起来"变得极简,代价是这些工程细节需要你自己补。补齐了,才叫服务。