




listen函数绑定端口失败的常见原因:端口被占用或权限不足;Linux/macOS下1024以下端口需root权限;Windows可能因TIME_WAIT残留导致;应检查占用并改用高编号端口。
Go 中用 net.Listen("tcp", ":8080") 启动服务器时,如果返回 "address already in use" 错误,通常不是代码问题,而是端口被占用或权限不足。Linux/macOS 下 1024 以下端口需要 root 权限;Windows 则可能因上次进程未退出干净导致 TIME_WAIT 状态残留。
lsof -i :8080(macOS/Linux)或 netstat -ano | findstr :8080(Windows)":8081")绕过权限限制":8080" 而非 "127.0.0.1:8080",否则无法响应外部请求Listener.Accept() 是阻塞调用,但每次 accept 返回的是一个 net.Conn,它本身不自动读写——你得自己启动 goroutine 去 Read 和 Write,否则新连接会卡住,后续连接也无法 accept。
go handleConn(conn) 是新手最常犯的错误,表现是只能处理第一个连接sync.WaitGroup 管理生命周期conn.Close() 后继续读写,会导致 "use of closed network connection"
TCP 连接关闭时,conn.Read() 不会报错,而是返回 n == 0 且 err == io.EOF;而长时间无数据时,默认无读超时,客户端断连后服务端可能一直阻塞。
err == io.EOF 并正常退出读循环,而不是当成异常 panicconn.SetReadDeadline(time.Now().Add(30 * time.Second)),否则空闲连接会无限占着 goroutinebufio.Reader 可提升小包读取效率,但注意 ReadString('\n') 遇到超时或 EOF 会返回部分数据 + error,需手动处理缓冲区以下是最简可用的 TCP 回声服务器核心逻辑,去掉日志和错误恢复,仅保留主干:
listener, _ := net.Listen("tcp", ":8080")
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
continue // 如临时资源不足,跳过本次
}
go func(c net.Conn) {
defer c.Close()
buf := make([]byte, 1024)
for {
n, err 
:= c.Read(buf)
if n > 0 {
c.Write(buf[:n]) // 回传收到的内容
}
if err != nil {
if err == io.EOF {
return
}
return
}
}
}(conn)
}真正上线时还得加连接数限制、心跳检测、粘包处理——但这些不是 listen/accept 的责任,而是协议层该解决的事。别一上来就堆 gob 或 json 编解码,先确保裸字节收发稳定。