{"record":{"id":"83288286ef666d03","repo":"unknwon/the-way-to-go_ZH_CN","slug":"malformed-command-832882","errorCode":null,"errorMessage":"malformed command","messagePattern":"malformed command","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"eBook/Discussion_about_16.10.md","lineNumber":53,"sourceCode":"\n3、这个可能和每个人的习惯（自己写代码的思路、风格）或者说适应（看其他人的代码时能很快习惯作者的代码风格）有关，我每次看代码都会先略过错误处理的部分，那么剩下的就是理想情况下的程序逻辑了，如果对某一处心存疑惑那么就再仔细看这部分的代码。毕竟我们写的代码绝大多数情况下是希望它按理想的情况跑的，\n\n_ _ _\n\n### 关于16.10.2的第二个代码示例\n\n16.10.2小结中关于错误处理的第二个代码示例是推荐给我们的错误处理方式，对于其推荐的这种方式，个人认为是有一定的适用范围的，并不适合大多数的错误处理，反而在处理某些业务逻辑时可以使用，比如将不符合业务逻辑的情况视作一种错误（自定义）来统一做处理。\n\n**书中代码示例二**：\n\n```Go\nfunc httpRequestHandler(w http.ResponseWriter, req *http.Request) {\n    err := func () error {\n        if req.Method != \"GET\" {\n            return errors.New(\"expected GET\")\n        }\n        if input := parseInput(req); input != \"command\" {\n            return errors.New(\"malformed command\")\n        }\n        // 可以在此进行其他的错误检测\n    } ()\n\n        if err != nil {\n            w.WriteHeader(400)\n            io.WriteString(w, err)\n            return\n        }\n        doSomething() ...\n```\n\n1、代码示例二中对不符合业务逻辑的两种情况做了归类，并自定义了错误，做了统一的处理。这样从业务层面来看，将不符合业务逻辑的情况视为错误，统一写到了匿名函数中，剩下了一个统一的错误处理与正常的业务逻辑。或许采用这种方式处理这类场景还不错，但是如果换作下面的这个示例可能就不是很合理了。\n\n下面的示例一是采用了作者推荐的统一处理错误方式，示例二使用的是通常的错误处理方式\n\n**示例一**：\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/Discussion_about_16.10.md#L35-L71","documentation":"Quoted duplicate of the second 16.10.2 check inside Discussion_about_16.10.md: after the method check, parseInput(req) must equal the literal \"command\" or the closure returns errors.New(\"malformed command\"), which the outer handler writes as a 400. The surrounding discussion notes this style fits business-logic violations (custom errors for rule breaches) more than general error handling.","triggerScenarios":"A GET request whose parsed input is not exactly \"command\": trailing whitespace/newline, different case, extra parameters folded in by a naive parseInput, or a different command word entirely.","commonSituations":"Fixed-vocabulary command endpoints; missing TrimSpace/Lower normalization before comparison; clients appending version query strings; a stubbed parseInput during development that returns raw form values.","solutions":["Normalize before comparing: strings.TrimSpace then strings.ToLower on the parsed input","Validate against a command table (map[string]func()) so the vocabulary lives in one place","Include the rejected value in diagnostics with %q, while keeping the client-facing response generic","Prefer distinct routes per command so malformed inputs fail routing, not business logic"],"exampleFix":"// before\nif input := parseInput(req); input != \"command\" {\n\treturn errors.New(\"malformed command\")\n}\n\n// after\ninput := strings.TrimSpace(parseInput(req))\nif _, ok := commands[strings.ToLower(input)]; !ok {\n\treturn fmt.Errorf(\"malformed command %q\", input)\n}","handlingStrategy":"validation","validationCode":"input := strings.TrimSpace(strings.ToLower(parseInput(req)))\nif _, ok := commands[input]; !ok {\n\thttp.Error(w, \"malformed command\", http.StatusBadRequest)\n\treturn\n}","typeGuard":null,"tryCatchPattern":"if _, ok := commands[strings.ToLower(strings.TrimSpace(parseInput(req)))]; !ok {\n\thttp.Error(w, \"malformed command\", http.StatusBadRequest)\n\treturn\n}","preventionTips":["Normalize (trim, lowercase) before comparing protocol tokens","Centralize the command vocabulary in one map so the check and the dispatch share it","Log rejected values with %q server-side to catch encoding issues (percent-encoded newlines, etc.)","Contract-test the full valid vocabulary so additions update the validator automatically"],"tags":["go","http","input-validation","discussion"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}