unknwon/the-way-to-go_ZH_CN · error

malformed command

Error message

malformed command

What it means

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.

Source

Thrown at eBook/16.10.md:53

    return
}
err2 := api.Func2()
if err2 != nil {
...
    return
}    
```

首先,包括在一个初始化的 `if` 语句中对函数的调用。但即使代码中到处都是以 `if` 语句的形式通知错误(通过打印错误信息)。通过这种方式,很难分辨什么是正常的程序逻辑,什么是错误检测或错误通知。还需注意的是,大部分代码都是致力于错误的检测。通常解决此问题的好办法是尽可能以闭包的形式封装你的错误检测,例如下面的代码:

```go
func httpRequestHandler(w http.ResponseWriter, req *http.Request) {
    err := func () error {
        if req.Method != "GET" {
            return errors.New("expected GET")
        }
        if input := parseInput(req); input != "command" {
            return errors.New("malformed command")
        }
        // 可以在此进行其他的错误检测
    } ()

        if err != nil {
            w.WriteHeader(400)
            io.WriteString(w, err)
            return
        }
        doSomething() ...
```

这种方法可以很容易分辨出错误检测、错误通知和正常的程序逻辑(更详细的方式参考[第 13.5 小节](13.5.md))。

**在开始阅读[第 17 章](17.0.md)前,先回答下列 2 个问题:**

- 问题 16.1:总结你能记住的所有关于 `, ok` 模式的情况。

View on GitHub (pinned to 7a54d34d36)

Solutions

  1. Normalize before comparing: input := strings.TrimSpace(strings.ToLower(parseInput(req)))
  2. Validate against a command table instead of one literal: if _, ok := commands[input]; !ok { return 400 } — new commands then need no new if-branch
  3. Echo the bad value in the error to speed debugging: fmt.Errorf("malformed command %q (expected %q)", input, "command")
  4. Reject at the route when possible (distinct paths per command) so routing mistakes never reach this branch

Example fix

// before
if input := parseInput(req); input != "command" {
	return errors.New("malformed command")
}

// after
input := strings.TrimSpace(parseInput(req))
if _, ok := commands[strings.ToLower(input)]; !ok {
	return fmt.Errorf("malformed command %q", input)
}
Defensive patterns

Strategy: validation

Validate before calling

input := strings.TrimSpace(strings.ToLower(parseInput(req)))
if input != "command" {
	http.Error(w, "malformed command", http.StatusBadRequest)
	return
}

Try / catch

err := func() error {
	if input := parseInput(req); input != "command" {
		return fmt.Errorf("malformed command %q", input)
	}
	return nil
}()
if err != nil {
	http.Error(w, err.Error(), http.StatusBadRequest)
	return
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15). Data as JSON: /api/errors/ed8721e258fcc7ea. Report an issue: GitHub.