net.listen 监听 0.0.0.0:8080 失败常见于权限不足或端口被占;需检查错误、设读写 deadline、正确处理连接关闭与粘包,并依协议类型选择 net/http 或 raw tcp。

net.Listen 为什么监听不了 0.0.0.0:8080?
常见现象是 listen tcp :8080: bind: permission denied 或 listen tcp 127.0.0.1:8080: bind: address already in use。前者多因端口 "0.0.0.0:8080",Go 也会尝试绑定所有接口,若本地已有进程占了 127.0.0.1:8080,net.Listen 仍会失败。
- 用
lsof -i :8080(macOS/Linux)或netstat -ano | findstr :8080(Windows)查占用进程 - 避免硬写
"0.0.0.0:8080";直接用":8080"更稳妥,Go 会自动适配 IPv4/IPv6 双栈(除非系统禁用 IPv6) - 监听
":80"等特权端口时,Linux/macOS 下必须加sudo,Windows 通常无此限制
Accept 后的 conn 一定要显式 Close 吗?
必须。Go 的 net.Listener.Accept 返回的 net.Conn 是底层文件描述符封装,不调 Close() 就不会释放资源。连接数一多,很快触发 too many open files 错误——这不是 Go 的 bug,是操作系统对每个进程能打开的 fd 数有限制(通常是 1024)。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 在
goroutine里处理连接时,defer conn.Close()要放在goroutine函数体最开头,而不是外层 - 不要在
Accept循环里直接读写conn,否则阻塞整个服务;必须起go handleConn(conn) -
conn.SetReadDeadline和conn.SetWriteDeadline建议设,防止客户端僵死拖垮服务
为什么 Read 会卡住、Write 会 panic?
典型错误是忽略 conn.Read 返回的 n, err 中的 err。比如客户端断开时,Read 返回 n == 0 且 err == io.EOF;若只检查 n > 0 就继续处理,下一次 Read 会阻塞(没设 deadline 的话)。而 Write 对已关闭连接调用,会立即 panic:write tcp 127.0.0.1:8080->127.0.0.1:54321: use of closed network connection。
- 每次
Read后必须检查err:若err != nil,且不是io.EOF或临时错误(err.Temporary()),就该break并Close -
Write前不必“预检连接是否存活”,但写完要检查err;一旦出错(尤其是broken pipe类),立刻Close - 别用
fmt.Fprintln(conn, ...)做协议交互——它不保证原子性,且换行符可能干扰二进制协议
要不要用 net/http 而不是 raw TCP?
取决于你传的是什么。如果协议是 HTTP(哪怕只是简单 GET /health)、需要 TLS、要复用连接、要 header/body 解析,那 net/http 是更稳的选择;但如果协议是自定义二进制包、心跳帧、或需精细控制收发时机(比如游戏服务器、IoT 设备通信),就必须用 net.Listen + conn 手动处理。
-
net/http.Server底层也是调net.Listen,但它把 Accept/Read/Write/Parse/WriteHeader 封装掉了,你失去对连接生命周期的掌控 - HTTP 服务默认开启 keep-alive,连接复用带来性能提升,但也意味着单个
conn可能持续几分钟,要特别注意超时设置(ReadTimeout,WriteTimeout,IdleTimeout) - raw TCP 没有消息边界概念,
Read可能只读到半个包;必须自己实现粘包/拆包逻辑(如固定头长、分隔符、长度前缀)
conn 设置读写 deadline,也没有在 goroutine 退出前确保 Close 被调用——这两点在压测时才会暴露,但线上扛不住真实流量。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










