Go TCP服务器必须显式绑定0.0.0.0:8080才能外网访问,否则默认仅监听127.0.0.1;每个连接需用goroutine并发处理并defer关闭;读取须用bufio.Scanner或循环Read防止丢数据;关闭listener前须用WaitGroup等待活跃连接结束。
0.0.0.0:8080 或 127.0.0.1:8080
Go 的 net.Listen 不会默认监听所有接口,省略 IP 会导致只绑 127.0.0.1(本地回环),外部机器连不上。生产环境若需外网访问,得写成 "0.0.0.0:8080";仅本机调试可选 "127.0.0.1:8080"。
常见错误现象:服务启动无报错,curl localhost:8080 成功,但换一台机器 telnet your-ip 8080 超时——八成是监听地址写成了 ":8080"(Go 会按平台默认解析,Linux 下常为 127.0.0.1)。
listener.Accept() 是阻塞调用,返回一个 net.Conn。如果不启 goroutine,整个服务器就卡在当前连接的读写上,无法接受新连接。
conn 启动独立 goroutine,例如 go handleConnection(conn)
handleConnection(con
n) 同步执行,服务器退化成串行单连接conn.Close(),否则连接泄漏bufio.Scanner 或循环 conn.Read(),不能只调一次TCP 是流式协议,conn.Read() 可能只读到部分数据,甚至 0 字节(比如对端关闭连接)。直接读一次就返回,会丢消息或提前退出。
推荐用 bufio.Scanner 简化按行读取:
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
line := scanner.Text()
fmt.Fprintf(conn, "echo: %s\n", line)
}
if err := scanner.Err(); err != nil {
log.Printf("scan error: %v", err)
}
如果需要处理二进制或自定义分隔符,就得手动循环 conn.Read(buf),检查返回字节数和 io.EOF。
listener.Close() 不会自动等待已 Accept 的连接处理完。如果主 goroutine 直接退出,正在运行的 handleConnection 可能被强制终止,导致 write on closed network connection 错误。
signal.Notify 捕获 os.Interrupt,用 sync.WaitGroup 计数活跃连接wg.Add(1),goroutine 结束前 wg.Done(),关闭 listener 后 wg.Wait()