先学 net/http 是因首个可运行API服务必用它,能快速验证基础理解并直面HTTP生命周期与常见陷阱;随后 encoding/json 解决JSON序列化问题,os/io 支撑文件与流操作。

从 net/http 开始学,不是因为“它最重要”,而是因为你写第一个能跑通的 API 服务时,绕不开它——而且一上来就踩坑。
为什么先啃 net/http?
几乎所有 Go 新手的第一个可运行服务,都是靠 http.HandleFunc + http.ListenAndServe 搭出来的。它短、快、有反馈,能立刻验证你对包、函数、main 入口的理解是否到位。
- 它强制你面对真实 HTTP 生命周期:请求读取、路由分发、响应写出
- 你会立刻遇到关键陷阱:
r.ParseForm()和json.NewDecoder(r.Body).Decode()不能混用——前者会提前读空r.Body,后者再读就返回空数据 - 它自然引出
io、encoding/json、strings等后续高频依赖,形成学习动线
encoding/json 必须紧随其后,重点盯住时间与结构体序列化
只要你的 API 返回 JSON,就逃不开这个包。但新手常卡在两个地方:时间格式不对、嵌套结构体解码失败。
-
time.Time默认序列化为 RFC3339 字符串(如"2026-01-12T13:11:00+08:00"),若后端要求"2006-01-02",必须自定义类型:type MyTime time.Time+ 实现MarshalJSON方法 - 结构体字段要导出(首字母大写),且建议显式加
json:tag,避免字段名大小写或下划线不一致导致解码为零值 - 用
json.Unmarshal解码前,确保目标变量已初始化(如var u User而非var u *User且未分配)
os 和 io 是文件与流操作的底层基础,别跳过缓冲细节
读配置、写日志、上传文件——这些看似“业务逻辑”的事,底层全靠它们。但新手容易忽略流式处理的边界行为。
立即学习“go语言免费学习笔记(深入)”;
-
io.Copy内部用 32KB 缓冲区,适合大文件;小数据(如几 KB 的 JSON 响应体)用io.WriteString更轻量,但注意它不自动换行 -
bufio.Scanner默认单行上限 64KB,读超长日志行会直接Scan() == false且Err()报错,需提前调用scanner.Buffer(make([]byte, 64*1024), 1 扩容 -
os.OpenFile的 flag 参数易错:os.O_CREATE|os.O_WRONLY|os.O_APPEND是追加写,漏掉os.O_CREATE会在文件不存在时报"no such file"
sync 和 context 不是“进阶内容”,而是并发服务的生存底线
一旦你把 HTTP handler 改成启动 goroutine 处理耗时任务,sync.WaitGroup 和 context.Context 就不再是可选项。
- 用
sync.Mutex保护共享 map 时,别只锁写不锁读——Go 的 map 并发读写 panic 是 runtime 级错误,无法 recover -
context.WithTimeout必须传给下游 HTTP client、DB query、channel receive,否则超时控制形同虚设 - 别在 goroutine 里直接用
http.Request.Context(),它可能已被 cancel;应通过参数显式传递派生 context
标准库不是按字母顺序学的,而是按你写代码时“哪块先报错”来排优先级。真正难的不是记函数签名,而是理解每个包在什么场景下会静默失败、什么时候需要手动干预缓冲或生命周期——这些细节,往往只在本地跑通、上线压测、日志突增时才露头。










