unknwon/the-way-to-go_ZH_CN · error
Error:
Error message
Error:
What it means
Panic raised by checkError in the chapter-15 TCP chat client (client1.go). Every network operation in the exercise funnels through checkError, which converts any non-nil error from conn.Write into a program-terminating panic with message 'Error: <err>'. The design is intentional for brevity: one failed send kills the whole client process.
Source
Thrown at eBook/exercises/chapter_15/client1.go:44
trimmedClient := strings.Trim(clientName, "\r\n") // "\r\n" voor Windows, "\n" voor Linux
for {
fmt.Println("What to send to the server? Type Q to quit. Type SH to shutdown server.")
input, _ = inputReader.ReadString('\n')
trimmedInput := strings.Trim(input, "\r\n")
// fmt.Printf("input:--%s--",input)
// fmt.Printf("trimmedInput:--%s--",trimmedInput)
if trimmedInput == "Q" {
return
}
_, error = conn.Write([]byte(trimmedClient + " says: " + trimmedInput))
checkError(error)
}
}
func checkError(error error) {
if error != nil {
panic("Error: " + error.Error()) // terminate program
}
}
View on GitHub (pinned to 7a54d34d36)
Solutions
- Start the companion server (server1.go) first and confirm it is listening on the exact host:port the client dials, then restart the client
- Replace checkError(error) after conn.Write with inline handling: on error, print it, close the connection, and return (or reconnect) instead of panicking
- If the abort style must stay, wrap the client loop in a deferred recover that prints the panic value and exits with a friendly message
- Read the error suffix: 'broken pipe'/'connection reset' means the peer went away — restart the server rather than hunting for a client bug
Example fix
// before
_, error = conn.Write([]byte(trimmedClient + " says: " + trimmedInput))
checkError(error)
// after
if _, err := conn.Write([]byte(trimmedClient + " says: " + trimmedInput)); err != nil {
fmt.Fprintln(os.Stderr, "send failed:", err)
return
} Defensive patterns
Strategy: try-catch
Validate before calling
func serverUp(addr string) bool {
c, err := net.DialTimeout("tcp", addr, 2*time.Second)
if err != nil {
return false
}
c.Close()
return true
}
// before entering the chat loop:
if !serverUp(serverAddr) {
log.Fatal("chat server is not reachable at", serverAddr)
} Try / catch
// Go's catch: deferred recover around the write loop
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(os.Stderr, "client aborted:", r)
os.Exit(1)
}
}()
for {
_, err := conn.Write(msg)
if err != nil { // prefer this: never let write errors reach panic
break
}
} Prevention
- Start the companion server before the client and share one addr constant between them
- Treat write/read errors as loop-exit conditions, not panic triggers
- Probe the server with net.DialTimeout before investing in an interactive session
When it happens
Trigger: conn.Write([]byte(trimmedClient + " says: " + trimmedInput)) returns a non-nil error: the companion server1.go exited, the TCP connection was reset by the peer, or the network path dropped between connect and send (errors like 'broken pipe' or 'connection reset by peer').
Common situations: Starting client1.go before server1.go (or after the server itself panicked via its own checkError); typing 'Q'-follow-up messages after the server closed the socket; firewall/NAT dropping an idle connection; dialing the wrong host/port so the failure surfaces at net.Dial just before this loop.
Related errors
- Error:
- "ERROR: " + info + " " + error.Error()
- "Dial: " + err.Error()
- pkg: %v
- %d is out of the int32 range
AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15).
Data as JSON: /api/errors/d4a1941afa29bb70.
Report an issue: GitHub.