{"record":{"id":"9a0ff4055b2721d0","repo":"unknwon/the-way-to-go_ZH_CN","slug":"listenandserve-err-error","errorCode":null,"errorMessage":"\"ListenAndServe: \" + err.Error()","messagePattern":"\"ListenAndServe: \" \\+ err\\.Error\\(\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"eBook/15.11.md","lineNumber":39,"sourceCode":"\nfunc server(ws *websocket.Conn) {\n\tfmt.Printf(\"new connection\\n\")\n\tbuf := make([]byte, 100)\n\tfor {\n\t\tif _, err := ws.Read(buf); err != nil {\n\t\t\tfmt.Printf(\"%s\", err.Error())\n\t\t\tbreak\n\t\t}\n\t}\n\tfmt.Printf(\" => closing connection\\n\")\n\tws.Close()\n}\n\nfunc main() {\n\thttp.Handle(\"/websocket\", websocket.Handler(server))\n\terr := http.ListenAndServe(\":12345\", nil)\n\tif err != nil {\n\t\tpanic(\"ListenAndServe: \" + err.Error())\n\t}\n}\n```\n\n示例 15.25 [websocket_client.go](examples/chapter_15/websocket_client.go)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\t\"websocket\"\n)\n\nfunc main() {\n\tws, err := websocket.Dial(\"ws://localhost:12345/websocket\", \"\",\n\t\t\"http://localhost/\")\n\tif err != nil {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/15.11.md#L21-L57","documentation":"Panic in the WebSocket echo server main (section 15.11): after registering http.Handle(\"/websocket\", websocket.Handler(server)), a failure of http.ListenAndServe(\":12345\", nil) is escalated with panic(\"ListenAndServe: \" + err.Error()). The panic text names whatever the net layer reported.","triggerScenarios":"ListenAndServe returns a non-nil error — most commonly 'listen tcp :12345: bind: address already in use' because another instance or process owns the port, or 'permission denied' when binding a privileged port without root.","commonSituations":"Running the server twice during development; a previous crashed instance still holding the socket; port 12345 occupied by an unrelated service; deploying to an environment where the port was not exposed/allocated.","solutions":["Free the port: find the holder (lsof -i :12345 or ss -ltnp) and stop it, or change the port in the code/flag","Bind 127.0.0.1:12345 for local dev to avoid clashing with LAN-facing services","Replace the panic with log.Fatal(\"ListenAndServe: \", err) for a clean, logged exit","Ensure prior instances shut down gracefully so the socket is released before restart"],"exampleFix":"// before\nerr := http.ListenAndServe(\":12345\", nil)\nif err != nil {\n    panic(\"ListenAndServe: \" + err.Error())\n}\n\n// after\nif err := http.ListenAndServe(\"127.0.0.1:12345\", nil); err != nil {\n    log.Fatal(\"ListenAndServe: \", err)\n}","handlingStrategy":"validation","validationCode":"// claim the port first; if this fails you get a clear reason, not a panic\nfunc portAvailable(addr string) bool {\n    ln, err := net.Listen(\"tcp\", addr)\n    if err != nil {\n        return false\n    }\n    ln.Close()\n    return true\n}\n\nif !portAvailable(\":12345\") {\n    log.Fatal(\":12345 already in use — stop the other instance or change the port\")\n}","typeGuard":null,"tryCatchPattern":"// if you keep the panic, at least exit cleanly from it\ndefer func() {\n    if r := recover(); r != nil {\n        log.Fatal(\"server aborted:\", r)\n    }\n}()\nerr := http.ListenAndServe(\":12345\", nil)","preventionTips":["Run exactly one instance per port; shut the previous one down before restarting","Make the port configurable (flag) so clashes have an easy workaround","Bind 127.0.0.1 for local dev to avoid colliding with LAN-facing services"],"tags":["go","http","websocket","server","port-in-use","panic"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}