unknwon/the-way-to-go_ZH_CN · error
expected GET
Error message
expected GET
What it means
Error from the closure-based validation in the eBook's httpRequestHandler example (16.10.2): the anonymous func checks req.Method != "GET" first and returns errors.New("expected GET") for any other verb; the outer code turns it into a 400 via w.WriteHeader(400) and io.WriteString(w, err). The snippet demonstrates concentrating all request validation in one closure so the handler body stays clean.
Source
Thrown at eBook/16.10.md:50
... err1 := api.Func1()
if err1 != nil {
fmt.Println("err: " + err.Error())
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 个问题:**View on GitHub (pinned to 7a54d34d36)
Solutions
- Fix the client to use GET if the operation is a read: fetch(url) defaults to GET — remove method: 'POST'; drop curl -d
- If other verbs are legitimate, return 405 Method Not Allowed with an Allow header instead of a bare 400 — 405 is the correct status for a wrong verb
- Route by verb so the handler is never reached with the wrong method: Go 1.22+ net/http mux patterns like mux.HandleFunc("GET /path", h)
- Compare against the http.MethodGet constant instead of the literal "GET" to avoid typo class bugs
Example fix
// before (inside the closure)
if req.Method != "GET" {
return errors.New("expected GET")
}
// ...
if err != nil {
w.WriteHeader(400)
io.WriteString(w, err)
return
}
// after
if req.Method != http.MethodGet {
w.Header().Set("Allow", http.MethodGet)
w.WriteHeader(http.StatusMethodNotAllowed)
io.WriteString(w, "expected GET")
return nil
} Defensive patterns
Strategy: validation
Validate before calling
// register the handler so only GET reaches it (Go 1.22+ method patterns)
mux.HandleFunc("GET /command", httpRequestHandler) Try / catch
err := func() error {
if req.Method != http.MethodGet {
return errors.New("expected GET")
}
// further checks...
return nil
}()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
} Prevention
- Compare with the http.MethodGet constant, never a bare "GET" string
- Return 405 + Allow header for wrong verbs; reserve 400 for malformed payloads
- Re-verify the client verb (fetch/axios/curl) after every API change; handle OPTIONS preflight explicitly or via CORS middleware
- Use method-aware routing so wrong-verb requests never enter handler logic
When it happens
Trigger: Any non-GET request reaching this handler: POST/PUT/DELETE from a form submission, a CORS preflight OPTIONS, or curl defaulting to POST when given -d. The method check runs before parseInput, so a wrong verb always fails here even with a valid body.
Common situations: Front-end switched to fetch with method POST while the backend still demands GET; health-checkers and proxies sending HEAD; browser CORS preflight OPTIONS hitting the route; copy-pasting the book handler without aligning the allowed method with the client.
Related errors
- expected GET
- I won't be able to do a sqrt of negative number!
- things aren’t good
- malformed command
- key not found
AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15).
Data as JSON: /api/errors/fcf6693d55ba6e41.
Report an issue: GitHub.