{"record":{"id":"ed8721e258fcc7ea","repo":"unknwon/the-way-to-go_ZH_CN","slug":"malformed-command","errorCode":null,"errorMessage":"malformed command","messagePattern":"malformed command","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"eBook/16.10.md","lineNumber":53,"sourceCode":"    return\n}\nerr2 := api.Func2()\nif err2 != nil {\n...\n    return\n}    \n```\n\n首先，包括在一个初始化的 `if` 语句中对函数的调用。但即使代码中到处都是以 `if` 语句的形式通知错误（通过打印错误信息）。通过这种方式，很难分辨什么是正常的程序逻辑，什么是错误检测或错误通知。还需注意的是，大部分代码都是致力于错误的检测。通常解决此问题的好办法是尽可能以闭包的形式封装你的错误检测，例如下面的代码：\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\n这种方法可以很容易分辨出错误检测、错误通知和正常的程序逻辑（更详细的方式参考[第 13.5 小节](13.5.md)）。\n\n**在开始阅读[第 17 章](17.0.md)前，先回答下列 2 个问题：**\n\n- 问题 16.1：总结你能记住的所有关于 `, ok` 模式的情况。\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/16.10.md#L35-L71","documentation":"Second check inside the same 16.10.2 validation closure: after the method check passes, parseInput(req) extracts the input and compares it to the literal \"command\"; anything else returns errors.New(\"malformed command\"), which the outer handler writes as a 400. It illustrates chaining several validations in one closure before the handler's real work (doSomething) runs.","triggerScenarios":"A GET request whose parsed input is not exactly the string \"command\": trailing whitespace or newline (e.g. ?q=command%0A), case differences (\"Command\"), extra parameters or suffixes the naive parser includes, or an entirely different command word.","commonSituations":"CLI-over-HTTP protocols expecting a fixed vocabulary; forgetting strings.TrimSpace on extracted input; case-sensitive protocol tokens ('RUN' vs 'run'); clients appending query strings like ?v=2 that parseInput folds into the value; stubbed parseInput returning raw form values during development.","solutions":["Normalize before comparing: input := strings.TrimSpace(strings.ToLower(parseInput(req)))","Validate against a command table instead of one literal: if _, ok := commands[input]; !ok { return 400 } — new commands then need no new if-branch","Echo the bad value in the error to speed debugging: fmt.Errorf(\"malformed command %q (expected %q)\", input, \"command\")","Reject at the route when possible (distinct paths per command) so routing mistakes never reach this branch"],"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 input != \"command\" {\n\thttp.Error(w, \"malformed command\", http.StatusBadRequest)\n\treturn\n}","typeGuard":null,"tryCatchPattern":"err := func() error {\n\tif input := parseInput(req); input != \"command\" {\n\t\treturn fmt.Errorf(\"malformed command %q\", input)\n\t}\n\treturn nil\n}()\nif err != nil {\n\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\treturn\n}","preventionTips":["Normalize input (trim, lowercase) before comparing protocol tokens","Define the accepted vocabulary in one map/table and validate against it","Log the rejected value with %q server-side, but keep client responses generic","Add a contract test enumerating valid commands so vocabulary drift breaks CI, not users"],"tags":["go","http","input-validation","protocol"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}