# 多路复用器
也就是 ServeMux,它的作用就是实现 url 与处理器 handler 的映射(这里虽然说是处理器,但是实际上就是处理函数)
golang 中的实现:
type ServeMux struct { | |
mu sync.RWMutex | |
m map[string]muxEntry | |
es []muxEntry // slice of entries sorted from longest to shortest. | |
hosts bool // whether any patterns contain hostnames | |
} |
我们使用 http
库写一个简单的 serve
端:
package main | |
import ( | |
"io" | |
"log" | |
"net/http" | |
) | |
func main() { | |
http.HandleFunc("/test", | |
func(rw http.ResponseWriter, r *http.Request) { | |
io.WriteString(rw, "hello world!") | |
}) | |
err := http.ListenAndServe("0.0.0.0:33787", nil) | |
if err != nil{ | |
log.Fatal(err) | |
} | |
} |
直接调用了 http.handlerFunc
, http
库会使用系统默认的 ServerMux
,因此,在 err := http.ListenAndServe("0.0.0.0:33787", nil)
中第二个传入的参数就是 nil。
因为这个 defaultServerMux
是一个全局变量,也就是说,第三方代码也可以调用 http 库,然后修改这个 defaultServerMux
。所以我们需要自己定制一个多路复用器。
sm := http.NewServeMux() | |
sm.HandleFunc("/test", | |
func(rw http.ResponseWriter, r *http.Request) { | |
io.WriteString(rw, "hello world!") | |
}) | |
err := http.ListenAndServe("0.0.0.0:33787", sm) |
代码很简单,就是 new 一个 ServerMux
。然后传给 listen
。
# 静态文件访问
可以直接调用 GIN:
e := gin.Default() | |
e.Static("/files/", "./") | |
e.Run(":33787") | |
e.GET("/",func(c *gin.Context) {c.String(http.StatusOK,"hello world!")}) |
访问 myip:33787/files/C.html
,显示:
直接就可以把 html 文件给显示出来。
# 请求头
请求头格式 type Header map[string]string
可以看到请求头就是一个 string map,它会记录 request 的头信息,一般对于 request 都是取出 header
里信息的。
这里有关于请求头的各个参数信息: HTTP 请求头
查询请求头参数:
func Header(w http.ResponseWriter, r *http.Request) { | |
s := r.Header.Get("Accept") | |
fmt.Printf("r.Header: %v\n", r.Header) | |
fmt.Printf("s: %v\n", s) | |
fmt.Println("hello world") | |
w.Write([]byte(s)) | |
} | |
func main() { | |
http.HandleFunc("/header", Header) | |
err := http.ListenAndServe(":33787", nil) | |
if err != nil { | |
fmt.Println(err) | |
} | |
} |
比如查 Accept
,表示当前浏览器可以接受的文件类型,假设这里有 image/webp,表示当前浏览器可以支持 webp 格式的图片,那么当服务器给当前浏览器下发 webp 的图片时,可以更省流量。
# 请求体
就是 postman
发 get 或 post 携带的键值对,如果是 get 请求,那么 body 会内嵌在 url 里,如果是 post 请求就发送表单,这样发送密码时用 post 就安全。
http
包: req.body.read([]byte)
gin
: c.Param(string)
就能查键值对。
这个请求体比请求头常用。
e := gin.Default() | |
e.GET("/",func(c *gin.Context) {c.Param("name")}) |
# 响应头
这里有一篇文章列出了响应头参数:响应头参数
WriteHeader
:设置状态码
Header().set()
: 设置其他参数,注意要在 writeHeader 之前进行设置。
重定向:
func Header(w http.ResponseWriter, r *http.Request) { | |
w.Header().Set("Location", "https://www.google.com") | |
w.WriteHeader(301) | |
} | |
func main() { | |
http.HandleFunc("/header", Header) | |
http.ListenAndServe("0.0.0.0:33787",nil) | |
} |