4.2 网络编程
net 包基础
go
// IP 地址
ip := net.ParseIP("192.168.1.1")
ip4 := ip.To4()
// IP 网络
_, network, _ := net.ParseCIDR("192.168.1.0/24")
network.Contains(net.ParseIP("192.168.1.100"))
// DNS 查询
addrs, _ := net.LookupHost("google.com")
names, _ := net.LookupAddr("8.8.8.8")
mx, _ := net.LookupMX("gmail.com")
// TCP 连接
conn, _ := net.Dial("tcp", "google.com:80")
defer conn.Close()
conn.Write([]byte("GET / HTTP/1.0\r\n\r\n"))
buf, _ := io.ReadAll(conn)
// 监听
lis, _ := net.Listen("tcp", ":8080")
defer lis.Close()
for {
conn, _ := lis.Accept()
go handleConn(conn)
}http 客户端
go
// 简单 GET
resp, _ := http.Get("https://api.example.com/data")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
// 简单 POST
resp, _ = http.Post(
"https://api.example.com/users",
"application/json",
bytes.NewBuffer([]byte(`{"name":"Alice"}`)),
)
// 创建请求
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer token")
q := req.URL.Query()
q.Add("page", "1")
req.URL.RawQuery = q.Encode()
// 自定义客户端
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, _ = client.Do(req)
// POST JSON
user := User{Name: "Alice"}
body, _ := json.Marshal(user)
req, _ = http.NewRequest("POST", url, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")http 服务器
go
// 基础服务器
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
})
http.ListenAndServe(":8080", nil)
// Handler 接口
type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Custom handler")
}
http.Handle("/custom", &MyHandler{})
// 路由处理
http.HandleFunc("/users/:id", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
// 获取
case http.MethodPost:
// 创建
default:
http.Error(w, "Method not allowed", 405)
}
})
// 静态文件
http.Handle("/static/", http.StripPrefix("/static/",
http.FileServer(http.Dir("assets"))))
// 中间件
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
fmt.Printf("%s %s %v\n", r.Method, r.URL.Path, time.Since(start))
})
}Graceful Shutdown
go
server := &http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
}
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}()
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
// 优雅关闭
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatal(err)
}