# Golang HTTP 和 Web 开发 ## 问题 1. Go 的 http.Client 如何使用? 2. 如何实现 HTTP 服务器? 3. context 在 HTTP 中的作用是什么? 4. 如何处理 HTTP 超时? 5. 如何实现中间件(Middleware)模式? --- ## 标准答案 ### 1. HTTP Client #### **基本使用** ```go import ( "fmt" "io" "net/http" "time" ) func main() { // GET 请求 resp, err := http.Get("https://api.github.com") if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) } ``` --- #### **自定义 Client** ```go func main() { // 自定义 Transport(超时、代理等) tr := &http.Transport{ MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, } client := &http.Client{ Transport: tr, Timeout: 5 * time.Second, } resp, err := client.Get("https://api.github.com") // ... } ``` --- ### 2. HTTP Server #### **基本服务器** ```go import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } ``` --- #### **Server 高级用法** ```go func main() { server := &http.Server{ Addr: ":8080", Handler: myHandler, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 120 * time.Second, } server.ListenAndServe() } ``` --- ### 3. Context 在 HTTP 中的作用 #### **超时控制** ```go func handler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) defer cancel() // 使用 context req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.github.com", nil) client := &http.Client{} resp, err := client.Do(req) if err != nil { if ctx.Err() == context.DeadlineExceeded { http.Error(w, "Timeout", http.StatusRequestTimeout) return } http.Error(w, err.Error(), http.StatusInternalServerError) return } defer resp.Body.Close() // ... } ``` --- ### 4. 中间件模式 ```go type Middleware func(http.Handler) http.Handler 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, time.Since(start)) }) } func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") if token == "" { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) } func main() { var mux http.ServeMux mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, World!") }) // 链式中间件 handler := loggingMiddleware(authMiddleware(&mux)) http.ListenAndServe(":8080", handler) } ``` --- ### 5. 阿里 P7 加分项 **深度理解**: - 理解 Go 的 http.Client 和 http.Server 实现 - 理解 HTTP/2 支持 - 理解 context 的传播机制 **实战经验**: - 有开发高性能 HTTP 服务器的经验 - 有处理 HTTP 超时的经验 - 有实现中间件框架的经验 **性能优化**: - 理解如何优化 HTTP 客户端性能(连接池、并发) - 理解如何优化 HTTP 服务器性能(Handler 调度) - 理解如何处理慢客户端