用 net/http 启动最简服务只需三行代码:导入 net/http 包,调用 http.ListenAndServe(":8080", nil) 即可监听端口,但未注册路由时所有请求均返回 404。

Golang如何构建一个简单的HTTP服务器  第1张

net/http 启动最简服务

Go 自带的 net/http 包不需要额外依赖,三行就能跑起来。核心是调用 http.ListenAndServe,它会阻塞运行,监听指定地址并处理请求。

package main

import "net/http"

func main() {
    http.ListenAndServe(":8080", nil)
}

这段代码启动一个监听 :8080 的服务器,但目前没有注册任何路由,所有请求都会返回 404 page not found。它只是“能跑”,不是“能用”。

注册 http.HandleFunc 处理路径

要让服务器响应具体 URL,得用 http.HandleFunc 注册处理器函数。它接收两个参数:路径前缀(如 "/")和一个符合 func(http.ResponseWriter, *http.Request) 签名的函数。

  • 路径匹配是前缀匹配,"/api" 会匹配 /api/api/users,但不会匹配 /apix
  • 多个注册时,更长的路径前缀优先级更高(实际按注册顺序覆盖,建议避免重叠)
  • 空字符串 "" 等价于 "/",表示根路径
package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Hello, World!")
    })
    http.ListenAndServe(":8080", nil)
}

http.ServeMux 显式管理路由

直接用 nil 作为 http.ListenAndServe 的第二个参数,底层会使用默认的 http.DefaultServeMux。但显式创建 http.ServeMux 更可控,也方便测试或替换。

立即学习“go语言免费学习笔记(深入)”;

  • 避免意外污染全局 DefaultServeMux(尤其在库中注册 handler 时)
  • 便于单元测试:可传入构造好的 *http.ServeMuxhttptest.NewServer
  • 支持更清晰的路由组织,比如按模块分组注册
package main

import (
    "fmt"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprint(w, "ok")
    })
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Home page")
    })

    http.ListenAndServe(":8080", mux)
}

常见错误:端口被占用或权限不足

运行时报错 listen tcp :8080: bind: address already in usepermission denied 是高频问题。

  • address already in use:检查是否已有进程在监听该端口,可用 lsof -i :8080(macOS/Linux)或 netstat -ano | findstr :8080(Windows)定位并 kill
  • permission denied:尝试绑定 :80:443 等特权端口时,Linux/macOS 需要 root 权限;开发阶段建议改用 :8080:3000 等非特权端口
  • 忘记 return 导致后续逻辑执行:在 handler 中写完响应后不 return,可能意外继续执行下一行(比如又写一次 body),引发 http: multiple response.WriteHeader calls

真正上线时,别只靠 ListenAndServe —— 它不支持超时控制、优雅关闭、TLS 自动配置等,这些得靠封装 http.Server 实例来实现。