应使用 net.listen 启动 tcp 服务,它自动处理跨平台 socket 细节和 so_reuseaddr;read/write 需自行处理分包;用 context 控制 goroutine 生命周期;udp 应使用 readfromudp/writetoudp 成对调用。

用 net.Listen 启动 TCP 服务,别直接写 socket()
Go 没有暴露底层 socket 系统调用,也不需要你手动 bind/listen/accept。直接用标准库的 net.Listen 就行,它封装了所有平台差异。
常见错误是照着 C 或 Python 的思路去“造轮子”,比如试图用 syscall.Socket —— 不仅跨平台行为难控,还容易漏掉 fd 设置(如 SO_REUSEADDR),导致端口占用报错 address already in use。
-
net.Listen("tcp", ":8080")是最常用写法,自动启用SO_REUSEADDR,Windows/macOS/Linux 都一致 - 想复用已关闭连接的端口?加
SetReusePort(true)(Linux 3.9+、FreeBSD、macOS 10.11+ 支持),但注意:Go 1.19+ 才在net.ListenConfig中稳定支持 - UDP 用
net.ListenUDP,别用net.Listen("udp", ...)—— 后者不支持多播、无法设ReadBuffer
conn.Read 和 conn.Write 不保证一次收/发完
TCP 是流式协议,Read 可能只读到部分数据,Write 也可能只写出一部分。直接假设“一次调用就搞定一整条消息”是绝大多数粘包/截断问题的根源。
典型现象:客户端发了 "hello\nworld\n",服务端 Read 一次只拿到 "hello\nwo",下一次才拿到 "rld\n",业务逻辑直接崩。
- 自己处理分包?用
bufio.Scanner(按行)或bufio.Reader.ReadBytes('\n')(适合简单协议) - 要二进制协议或长度前缀?别手写循环读,用
binary.Read先读 4 字节长度,再io.ReadFull补齐 payload - 千万别用
conn.SetReadDeadline后无脑Read—— 超时会返回io.EOF或net.ErrTimeout,不区分连接关闭和超时,容易误判
goroutine 泄漏比连接泄漏更隐蔽
每个新连接都起一个 goroutine 处理很自然,但没配好退出机制就会累积 goroutine,直到内存耗尽或调度器卡死。
常见错误是只关 conn,却没通知处理 goroutine 停止。比如用 time.AfterFunc 关闭连接,但 goroutine 还在 Read 阻塞,根本收不到信号。
- 用
context.WithCancel控制生命周期:把ctx传进 handler,Read时用conn.SetReadDeadline+select等待ctx.Done() - 别在 handler 里直接
defer conn.Close()—— 如果 handler panic,defer不执行,连接一直挂着;改用defer func() { _ = conn.Close() }() - 用
runtime.NumGoroutine()在开发期打点,上线后结合 pprof 查看 goroutine profile,比等 OOM 再查快得多
UDP 场景下 ReadFromUDP 和 WriteToUDP 必须成对用
UDP 没有连接概念,net.Conn 接口在 UDP 上只是个假象。一旦你用 net.ListenUDP 得到 *net.UDPConn,就该用它的原生方法,而不是包装成 net.Conn 后调 Read/Write。
典型坑:用 conn.Write([]byte("ok")) 发 UDP 包,结果什么都没发出去——因为 UDPConn 的 Write 方法内部会忽略地址信息,只往上次 ReadFrom 的对端发,而首次调用时对端地址为空。
- 收包必须用
ReadFromUDP(buf),它返回实际来源地址addr - 回包必须用
WriteToUDP(buf, addr),显式指定目标地址 - 如果要做 server 并发处理多个 client,别为每个 client 新开
*net.UDPConn—— 单个UDPConn就支持并发收发,靠addr区分 client
真正麻烦的从来不是建连接或发数据,而是连接异常中断时的状态同步:对方静默断开、NAT 超时踢出、中间设备重置连接……这些场景下,Read 可能不报错,Write 可能延迟几秒才失败。得靠应用层心跳 + 读写超时组合判断,光靠 SetDeadline 不够稳。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











