Go中http.ListenAndServe未监听连接直接退出问题排查
问题
我编写了一个预期作为守护进程等待连接的Go简易应用,但程序启动后直接退出,无法监听请求,在进程列表中也找不到它。
代码如下:
package main import ( "fmt" "log" "net/http" ) func main() { fmt.Println("Start Server") log.Print("Start Server") http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, World! from linux") }) log.Print("Going to listen") if err := http.ListenAndServe(":80", nil); err != err { log.Print("getting error") log.Fatal(err) } fmt.Println("End Server") log.Print("End Server") }
编译运行命令及输出:
xxx@xxx:~/go_test$ CGO_ENABLED=0 go build -gcflags "all=-N -l" -o ./main umen@umen:~/go_test$ ./main Start Server 2023/11/15 07:40:22 Start Server 2023/11/15 07:40:22 Going to listen End Server 2023/11/15 07:40:22 End Server
尝试连接时出现错误:
xxx@xxx:~$ curl http://localhost curl: (7) Failed to connect to localhost port 80 after 0 ms: Connection refused
我遗漏了什么?
更新:移除log.Fatal后,程序仍启动后直接退出,无法监听GET请求。
解答
问题核心在于http.ListenAndServe的错误判断逻辑:
你写的条件err != err永远为false——一个变量不可能不等于自身。这导致代码既不会进入错误处理分支,还直接跳过了ListenAndServe的阻塞逻辑(正常情况下该函数会一直运行到服务出错退出),程序直接执行后续代码后退出。
正确的写法是判断err != nil,这样当ListenAndServe返回错误时才会触发日志并退出,正常情况下则会保持阻塞,维持服务运行。
修正后的代码:
package main import ( "fmt" "log" "net/http" ) func main() { fmt.Println("Start Server") log.Print("Start Server") http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, World! from linux") }) log.Print("Going to listen") if err := http.ListenAndServe(":80", nil); err != nil { log.Print("getting error") log.Fatal(err) } fmt.Println("End Server") log.Print("End Server") }
额外注意:Linux系统下监听80端口需要root权限,普通用户运行会触发权限不足错误。如果不想使用root,可更换为1024以上的端口(如8080),普通用户即可正常运行。
内容的提问来源于stack exchange,提问作者user63898
相关产品推荐
相关产品推荐

