{"record":{"id":"d741ae44e7ed24a8","repo":"unknwon/the-way-to-go_ZH_CN","slug":"error-d741ae","errorCode":null,"errorMessage":"Error: ","messagePattern":"Error: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"eBook/exercises/chapter_15/server1.go","lineNumber":64,"sourceCode":"\t\tif strings.Contains(input, \": WHO\") {\n\t\t\tDisplayList()\n\t\t}\n\t\t// extract clientname:\n\t\tix := strings.Index(input, \"says\")\n\t\tclName := input[0 : ix-1]\n\t\t//fmt.Printf(\"The clientname  is ---%s---\\n\", string(clName))\n\t\t// set clientname active in mapUsers:\n\t\tmapUsers[string(clName)] = 1\n\t\tfmt.Printf(\"Received data: --%v--\", string(buf))\n\t}\n}\n\n// advantage: code is cleaner,\n// disadvantage:  the server process has to stop at any error:\n//                a simple return continues in the function where we came from!\nfunc checkError(error error) {\n\tif error != nil {\n\t\tpanic(\"Error: \" + error.Error()) // terminate program\n\t}\n}\n\nfunc DisplayList() {\n\tfmt.Println(\"--------------------------------------------\")\n\tfmt.Println(\"This is the client list: 1=active, 0=inactive\")\n\tfor key, value := range mapUsers {\n\t\tfmt.Printf(\"User %s is %d\\n\", key, value)\n\t}\n\tfmt.Println(\"--------------------------------------------\")\n}\n","sourceCodeStart":46,"sourceCodeEnd":76,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/exercises/chapter_15/server1.go#L46-L76","documentation":"Panic from checkError in server1.go, the chapter-15 TCP chat server. Any error from Accept, Read, or Write — even from a single client — reaches checkError and crashes the entire server with 'Error: <err>'. The source comment itself flags the trade-off: 'the server process has to stop at any error: a simple return continues in the function where we came from'.","triggerScenarios":"A client disconnects abruptly (terminal closed, Ctrl-C) and the server's next conn.Read returns 'connection reset by peer'; or the listener socket fails (e.g. 'bind: address already in use') and the error reaches checkError, killing all connected users.","commonSituations":"One user closing their chat window kills the chat for everyone; starting a second server instance on a port the first still holds; running on a privileged port without permissions; long-lived demo servers hit by transient peer resets.","solutions":["Handle per-connection errors inside the client-serving goroutine: log, close that conn, and return — never panic out of it","Keep checkError only for fatal startup failures (resolve/listen); demote Accept errors to log-and-continue","Add a deferred recover inside each connection goroutine so an unexpected panic cannot take down the Accept loop","If the message says 'address already in use', stop the stale server process or pick another port before restarting"],"exampleFix":"// before\n// inside client loop:\nn, error := conn.Read(buf)\ncheckError(error)\n\n// after\nn, err := conn.Read(buf)\nif err != nil {\n    fmt.Fprintln(os.Stderr, \"client\", clName, \"disconnected:\", err)\n    conn.Close()\n    return\n}","handlingStrategy":"try-catch","validationCode":"func portFree(addr string) bool {\n    l, err := net.Listen(\"tcp\", addr)\n    if err != nil {\n        return false\n    }\n    l.Close()\n    return true\n}\n\nif !portFree(\":5000\") {\n    log.Fatal(\"port 5000 already in use — stop the stale server first\")\n}","typeGuard":null,"tryCatchPattern":"// per-goroutine recover so one bad client cannot kill the server\nfor {\n    conn, err := listener.Accept()\n    if err != nil { log.Println(\"accept:\", err); continue }\n    go func(c net.Conn) {\n        defer func() {\n            if r := recover(); r != nil {\n                log.Println(\"connection panic:\", r)\n            }\n        }()\n        defer c.Close()\n        serve(c)\n    }(conn)\n}","preventionTips":["Never share one fatal checkError across startup and per-connection code paths","Always defer conn.Close() in the owning goroutine","Log the remote address with every per-connection error so resets are diagnosable"],"tags":["go","network","tcp","server","panic","chat","goroutine"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}