HTTP 服务器实现
Go 内置的 net/http
包是最基础的 HTTP 服务器实现,无需依赖第三方库
go
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
// 匿名注册路由和处理函数
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World! %s", r.URL.Path)
})
//注册api路径路由和处理函数
http.HandleFunc("/api", apiHandler)
// 启动服务器(监听 80 端口)
log.Println("服务器启动在 :80")
log.Fatal(http.ListenAndServe(":80", nil))
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "API 路径: %s", r.URL.Path)
}
go标准库中文文档地址Go语言中文网
http.ListenAndServe
http.ListenAndServe(addr string, handler Handler) error
是 Go 标准库中启动 HTTP 服务器的入口函数,主要作用包括:
- 监听地址 :通过
addr
参数指定监听地址(如":8080"
)。 - 处理器注册 :
handler
参数为 HTTP 请求处理器(可为nil
,默认使用DefaultServeMux
路由)。 - 错误处理:返回错误信息(如端口占用)。
当 handler
为 nil
时,默认使用 http.DefaultServeMux
路由表,开发者可通过 http.HandleFunc()
或 http.Handle()
注册路由逻辑
底层实现细节
vbscript
server := &Server{
Addr: addr,
Handler: handler,
}
return server.ListenAndServe()
http.Server
结构体关键字段
go
type Server struct {
Addr string // 监听地址(默认":http"即80端口)
Handler Handler // 请求处理器(默认DefaultServeMux)
ReadTimeout time.Duration // 读取请求超时(含Header和Body)
WriteTimeout time.Duration // 写入响应超时(从接收请求开始计时)
IdleTimeout time.Duration // 空闲连接超时(默认使用ReadTimeout)
MaxHeaderBytes int // 请求头最大字节数(默认1MB)
TLSConfig *tls.Config // TLS配置(用于HTTPS)
ConnState func(net.Conn, ConnState) // 连接状态回调
ErrorLog *log.Logger // 错误日志记录器
}
通过http.Server
结构体配置服务器参数
lua
srv := &http.Server{
Addr: ":8080",
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 21, // 2MB
}
log.Fatal(srv.ListenAndServe())
常见错误场景
- 地址格式错误 :如
ListenAndServe("1234", nil)
缺少:
,需修正为":1234"
- 端口占用 :端口被其他进程占用时返回
EADDRINUSE
错误。 - Handler未实现 :若
Handler
未正确设置(如未注册路由),默认返回404
如果匹配项 后边加 / 。会匹配后边子路径。
http.HandleFunc()
http.HandleFunc()
用于为特定URL路径注册处理函数,当请求匹配该路径时,自动调用对应的处理逻辑。其函数签名如下:
go
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
-
pattern
:URL路径模式。 -
handler
:处理函数,签名必须为func(http.ResponseWriter, *http.Request)
。
go源代码截图:
编辑
底层实现
- 类型转换 :
http.HandleFunc()
内部将普通函数转换为http.HandlerFunc
类型 http.HandlerFunc类型。实现了 ServerHTTP 接口。
http.Handle
http.Handle
用于将URL路径模式(pattern
)与实现了http.Handler
接口的对象绑定,当请求匹配该路径时,调用其ServeHTTP
方法处理请求。函数签名如下:
go
func Handle(pattern string, handler Handler)
-
pattern
:路由路径 -
handler
:实现了http.Handler
接口的对象(需定义ServeHTTP(ResponseWriter, *Request)
方法)。
go
// 使用 HandleFunc
http.HandleFunc("/hello", func(w ResponseWriter, r *Request) { ... })
// 使用 Handle(需自定义 Handler 类型)
type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w ResponseWriter, r *Request) { ... }
http.Handle("/hello", &MyHandler{})
http.Handle与
http.HandleFunc
的对比
特性 | http.Handle |
http.HandleFunc |
---|---|---|
参数类型 | 需实现http.Handler 接口的对象 |
直接传入普通函数 |
灵活性 | 高(支持状态管理) | 低(仅适合简单逻辑) |
代码复杂度 | 较高(需定义结构体或类型) | 低(直接编写函数) |
适用场景 | 复杂业务逻辑、需复用状态的场景 | 快速注册简单路由 |
路由管理器
http.NewServeMux
是Go标准库net/http
中用于创建HTTP请求路由器 的核心函数。它的作用是将不同的URL路径映射到对应的处理函数(http.Handler
),实现请求的多路复用(Multiplexing)。路由器会根据请求的URL路径和HTTP方法,将请求分派给正确的处理逻辑。其核心功能包括:
- 路由注册 :通过
Handle()
或HandleFunc()
方法将 URL 路径与处理器(Handler
)绑定。 - 请求分发:根据请求的 URL 路径匹配已注册的路由规则,调用对应的处理函数。
- 隔离性 :与全局默认路由
DefaultServeMux
解耦,避免多模块路由冲突。
go
package main
import (
"log"
"net/http"
"time"
)
func main() {
server := &http.Server{
Addr: ":8080",
Handler: customMux(),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
}
log.Println("服务器启动在 :8080")
log.Fatal(server.ListenAndServe())
}
func customMux() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/api", apiHandler)
return mux
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "API 路径: %s", r.URL.Path)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!: %s", r.URL.Path)
}
路由匹配规则
1. 优先级原则
- 最长路径优先 :若多个模式匹配同一请求,选择路径更长的模式(如
/api
优先于/
)。 - 精确匹配优先 :非斜杠结尾的路径(如
/v2
)优先级高于前缀匹配路径(如/v2/
)。
2. 路径处理规则
-
末尾斜杠:
- 模式
/v1/
匹配所有以/v1/
开头的请求(如/v1/foo
)。 - 若访问
/v1
(无斜杠),自动重定向到/v1/
。
- 模式