go 项目中测试 http 服务时,需避免在测试文件中定义 `main()` 函数,并确保测试函数以大写 `test` 开头、属于同一 `package main`,才能被 `go test` 正确识别和执行。
在 Go 中为基于 net/http 的 Web 应用编写测试,核心原则是:测试文件(如 beacon_test.go)必须与主程序文件(如 beacon.go)位于同一包(package main),且不能包含 func main() —— 因为 main 函数仅允许在一个可执行包中出现一次。
你遇到的错误:
./beacon_test.go:11: main redeclared in this block
previous declaration at ./beacon.go:216正是因为 beacon_test.go 复制了官方 httptest 示例中的完整可运行程序(含 func main()),而该示例本意是独立演示,不可直接作为测试文件使用。
✅ 正确做法如下:
例如,假设 beacon.go 包含一个简单 HTTP handler:
// beacon.go
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "OK")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}对应的测试文件应写为:
// beacon_test.go
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
handler(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status OK; got %v", w.Code)
}
if w.Body.String() != "OK" {
t.Errorf("expected body 'OK'; got %q", w.Body.String())
}
}⚠️ 注意事项:
总结:Go 的测试机制依赖严格的命名与包规则——测试函数不是“可执行程序”,而是由 go test 框架驱动的回调。摒弃复制粘贴完整 main 示例的习惯,转而聚焦于 testing.T 驱动的断言逻辑,才能写出健壮、可维护的 HTTP 测试代码。