1. HTTP
...大约 3 分钟
net/http
1. 使用标准库 func main() {
// 注册路由
http.HandleFunc("/", indexHandler)
http.HandleFunc("/hello", helloHandler)
// 监听并启动 HTTP 服务
log.Fatal(http.ListenAndServe(":8000", nil))
}
func indexHandler(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "URL.path = %q\n", req.URL.Path)
}
func helloHandler(w http.ResponseWriter, req *http.Request) {
// 输出所有 http 请求头 request.Header
for k, v := range req.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
}
indexHandler
:路由/
绑定的处理函数,响应当前请求的 URL 路径helloHandler
:路由/hello
绑定的处理函数,响应当前请求的请求头ListenAndServe(addr string, handler Handler)
:启动 Web 服务addr
:监听地址handler
:处理所有 HTTP 请求的实例,默认为 nil;可作为 Web 框架的入口
$ curl http://localhost:8000
URL.path = "/"
$ curl http://localhost:8000/hello
Header["User-Agent"] = ["curl/8.0.1"]
Header["Accept"] = ["*/*"]
Header["Accept-Encoding"] = ["gzip"]
http.Handler
接口
2. type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
http.Handler
是接口类型,只要自定义的类型实现了该接口,那么将自定义类型的实例作为ListenAndServe
的第二个参数传入,该实例将接管所有的 HTTP 请求的处理。
// Engine is the uni handler for all request
type Engine struct{}
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
switch req.URL.Path {
case "/":
fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
case "/hello":
for k, v := range req.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
default:
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
func main() {
engine := new(Engine)
log.Fatal(http.ListenAndServe(":8000", engine))
}
Engine
实现了http.Handler
接口,其方法ServeHTTP
有两个参数:http.ResponseWriter
:用于构造 HTTP Response*http.Request
:包含HTTP请求的所有信息
ListenAndServe
函数的第二参数传入创建的Engine
实例,接管所有的 HTTP 请求的处理
3. Gee 框架雏形
https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/Gee/day1-basic
重新组织上述代码,目录结构如下:
base3/
gee/
|--gee.go
|--go.mod
main.go
go.mod
base3/go.mod
:
module base3
go 1.20
require (
gee v0.0.0
)
// 将 gee 指向 ./gee
replace gee => ./gee
(备注:在 gov1.18 及之后可以使用 go workspace 替代 replace 使用)
使用 go work
$ go work init .
$ go work use ./gee
// base3/go.work
go 1.20
use (
.
./gee
)
// base3/go.mod
// 使用了 go work,无需使用 replace
module base3
go 1.20
require (
gee v0.0.0
)
3.1 gee.go
package gee
import (
"fmt"
"net/http"
)
// HandlerFunc defines the request handler used by gee engine
type HandlerFunc func(http.ResponseWriter, *http.Request)
// Engine implement the http.Handler
type Engine struct {
router map[string]HandlerFunc
}
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
key := req.Method + "-" + req.URL.Path
if handler, ok := engine.router[key]; ok {
handler(w, req)
} else {
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
key := method + "-" + pattern
engine.router[key] = handler
}
// GET add GET request route
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
engine.addRoute("GET", pattern, handler)
}
// POST add POST request route
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
engine.addRoute("POST", pattern, handler)
}
// Run start a http server
func (engine *Engine) Run(addr string) error {
return http.ListenAndServe(addr, engine)
}
// New is the constructor of gee.Engine
func New() *Engine {
return &Engine{
router: map[string]HandlerFunc{},
}
}
HandlerFunc
:自定义的请求处理函数,交由调用方实现Engine.router
:路由表,绑定请求方法及路径和对应的处理函数*Engine.addRoute
:添加新的路由映射到路由表中*Engine.Run
:封装http.ListenAndServe
函数*Engine.ServeHTTP
:实现的http.Handler
接口方法,根据请求获取对应的处理函数,路由表中不存在则返回 404
3.2 main.go
package main
import (
"fmt"
"gee"
"net/http"
)
func main() {
r := gee.New()
r.GET("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
})
r.GET("/hello", func(w http.ResponseWriter, req *http.Request) {
for k, v := range req.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
})
r.Run(":8000")
}
流程如下:
- 创建
gee.Engine
实例 - 注册路由,
/
和/hello
- 启动 HTTP 服务
启动并测试
$ curl http://localhost:8000
URL.path = "/"
$ curl http://localhost:8000/hello
Header["User-Agent"] = ["curl/8.0.1"]
Header["Accept"] = ["*/*"]
Header["Accept-Encoding"] = ["gzip"]
$ curl http://localhost:8000/path
404 NOT FOUND: /path
4. 小结
现阶段 Gee 的雏形已完成,实现了以下功能:
- 路由映射表
- 注册静态路由
- 启动 HTTP 服务
Reference
Powered by Waline v2.15.2