unknwon/the-way-to-go_ZH_CN · error
"ListenAndServe: " + err.Error()
Error message
"ListenAndServe: " + err.Error()
What it means
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.
Source
Thrown at eBook/15.11.md:39
func server(ws *websocket.Conn) {
fmt.Printf("new connection\n")
buf := make([]byte, 100)
for {
if _, err := ws.Read(buf); err != nil {
fmt.Printf("%s", err.Error())
break
}
}
fmt.Printf(" => closing connection\n")
ws.Close()
}
func main() {
http.Handle("/websocket", websocket.Handler(server))
err := http.ListenAndServe(":12345", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
```
示例 15.25 [websocket_client.go](examples/chapter_15/websocket_client.go)
```go
package main
import (
"fmt"
"time"
"websocket"
)
func main() {
ws, err := websocket.Dial("ws://localhost:12345/websocket", "",
"http://localhost/")
if err != nil {View on GitHub (pinned to 7a54d34d36)
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
Example fix
// before
err := http.ListenAndServe(":12345", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
// after
if err := http.ListenAndServe("127.0.0.1:12345", nil); err != nil {
log.Fatal("ListenAndServe: ", err)
} Defensive patterns
Strategy: validation
Validate before calling
// claim the port first; if this fails you get a clear reason, not a panic
func portAvailable(addr string) bool {
ln, err := net.Listen("tcp", addr)
if err != nil {
return false
}
ln.Close()
return true
}
if !portAvailable(":12345") {
log.Fatal(":12345 already in use — stop the other instance or change the port")
} Try / catch
// if you keep the panic, at least exit cleanly from it
defer func() {
if r := recover(); r != nil {
log.Fatal("server aborted:", r)
}
}()
err := http.ListenAndServe(":12345", nil) Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15).
Data as JSON: /api/errors/9a0ff4055b2721d0.
Report an issue: GitHub.