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

  1. Start the companion server (server1.go) first and confirm it is listening on the exact host:port the client dials, then restart the client
  2. Replace checkError(error) after conn.Write with inline handling: on error, print it, close the connection, and return (or reconnect) instead of panicking
  3. 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
  4. 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

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


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.