Go标准库无listenAndServe,须手动net.Listen+for循环Accept;每个conn需goroutine处理并设Read/Write deadline,Read/Write要检查n和err,避免阻塞与泄漏。

listenAndServe 不存在,得用 net.Listen + accept 循环
Go 标准库没有类似 http.ListenAndServe 那样开箱即用的 TCP 服务启动函数。你必须手动调用 net.Listen 创建监听套接字,再用 Accept 持续接收连接——这是最基础、也最容易漏掉循环控制的地方。
-
net.Listen("tcp", ":8080")返回net.Listener,只负责监听,不处理连接 - 必须显式写
for循环调用listener.Accept(),否则程序启动后立即退出 - 每个
conn是net.Conn接口,需单独 goroutine 处理,否则会阻塞下一个连接 - 忘记关闭
conn会导致文件描述符泄漏,尤其在高并发时很快 hit ulimit
读写要用 conn.Read/Write,不是 fmt.Scan/Fprintln
TCP 连接是字节流,fmt 包的函数默认操作 os.Stdin/os.Stdout,不能直接用于 net.Conn。必须用 conn.Read 和 conn.Write,且要处理返回的 n(实际读写字节数)和 err。
-
conn.Read([]byte)是阻塞调用,直到有数据或连接关闭;返回n, err,n == 0 && err == nil表示对端关闭写入(EOF) -
conn.Write([]byte)不保证一次发完,但标准实现中对小包通常能全写,仍建议检查n是否等于预期长度 - 不要用
fmt.Fscanf(conn, "%s", &buf):它依赖空格/换行分隔,而 TCP 无消息边界,容易卡住或错读 - 简单回显场景可用
io.Copy(conn, conn),但生产环境务必加超时和缓冲控制
必须设 Read/Write deadline,否则连接卡死无法释放
没有超时的 TCP 服务在客户端异常断连、网络中断或发送半截数据时,conn.Read 会永久阻塞,goroutine 泄漏,最终耗尽资源。
- 在
accept后立刻调用conn.SetReadDeadline和conn.SetWriteDeadline - 时间点用
time.Now().Add(30 * time.Second),不是固定间隔;每次读写前都需重设 - 超时错误是
net.ErrDeadlineExceeded,可据此主动关闭连接 - 如果用
io.ReadFull或bufio.Reader,deadline 仍需手动设置,它们不自动继承
package mainimport ( "log" "net" "time" )
func handleConn(conn net.Conn) { defer conn.Close() conn.SetReadDeadline(time.Now().Add(30 time.Second)) conn.SetWriteDeadline(time.Now().Add(30 time.Second))
buf := make([]byte, 1024) for { n, err := conn.Read(buf) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { log.Println("read timeout", conn.RemoteAddr()) } return } if n == 0 { return } _, _ = conn.Write(buf[:n]) conn.SetReadDeadline(time.Now().Add(30 * time.Second)) conn.SetWriteDeadline(time.Now().Add(30 * time.Second)) }}
func main() { lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatal(err) } defer lis.Close()
log.Println("TCP server listening on :8080") for { conn, err := lis.Accept() if err != nil { log.Println("accept error:", err) continue } go handleConn(conn) }}
真正麻烦的从来不是“怎么启动”,而是连接生命周期管理:什么时候关、谁来关、超时怎么判、错误怎么分。哪怕只是 echo 服务,
SetDeadline和defer conn.Close()漏掉任何一个,跑两天就出事。










