Go 通过 net/http 包提供了强大的 HTTP 服务器功能。
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
fmt.Println("服务器启动在 :8080")
http.ListenAndServe(":8080", nil)
}
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/about", aboutHandler)
http.HandleFunc("/contact", contactHandler)
fmt.Println("服务器启动在 :8080")
http.ListenAndServe(":8080", nil)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "首页")
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "关于我们")
}
func contactHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "联系我们")
}
package main
import (
"fmt"
"io"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 请求方法
fmt.Fprintf(w, "方法: %s\n", r.Method)
// 请求路径
fmt.Fprintf(w, "路径: %s\n", r.URL.Path)
// 查询参数
query := r.URL.Query()
fmt.Fprintf(w, "查询参数: %v\n", query)
// 请求头
fmt.Fprintf(w, "User-Agent: %s\n", r.Header.Get("User-Agent"))
// 请求体
body, _ := io.ReadAll(r.Body)
fmt.Fprintf(w, "请求体: %s\n", body)
// 客户端地址
fmt.Fprintf(w, "客户端地址: %s\n", r.RemoteAddr)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
package main
import (
"fmt"
"net/http"
)
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
return
}
// 解析表单
r.ParseForm()
// 获取表单值
username := r.FormValue("username")
password := r.FormValue("password")
fmt.Fprintf(w, "用户名: %s\n", username)
fmt.Fprintf(w, "密码: %s\n", password)
}
func main() {
http.HandleFunc("/login", formHandler)
http.ListenAndServe(":8080", nil)
}
package main
import (
"encoding/json"
"io"
"net/http"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
func jsonHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
return
}
// 读取请求体
body, _ := io.ReadAll(r.Body)
// 解析 JSON
var user User
json.Unmarshal(body, &user)
// 返回 JSON 响应
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"code": 0,
"message": "success",
"data": user,
})
}
func main() {
http.HandleFunc("/api/user", jsonHandler)
http.ListenAndServe(":8080", nil)
}
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
// 精确匹配
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/about", aboutHandler)
// 前缀匹配(以 / 结尾)
mux.HandleFunc("/api/", apiHandler)
// 动态路由(手动解析)
mux.HandleFunc("/user/", userHandler)
http.ListenAndServe(":8080", mux)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "首页")
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "关于我们")
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "API: %s", r.URL.Path)
}
func userHandler(w http.ResponseWriter, r *http.Request) {
// 从路径中提取用户 ID
userID := r.URL.Path[len("/user/"):]
fmt.Fprintf(w, "用户 ID: %s", userID)
}
package main
import (
"encoding/json"
"net/http"
"strconv"
"strings"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/users/", userHandler)
http.ListenAndServe(":8080", mux)
}
func usersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case "GET":
json.NewEncoder(w).Encode(users)
case "POST":
var user User
json.NewDecoder(r.Body).Decode(&user)
user.ID = len(users) + 1
users = append(users, user)
json.NewEncoder(w).Encode(user)
default:
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
func userHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
// 提取用户 ID
idStr := strings.TrimPrefix(r.URL.Path, "/users/")
id, _ := strconv.Atoi(idStr)
// 查找用户
var user *User
for i := range users {
if users[i].ID == id {
user = &users[i]
break
}
}
if user == nil {
http.Error(w, "用户不存在", http.StatusNotFound)
return
}
switch r.Method {
case "GET":
json.NewEncoder(w).Encode(user)
case "PUT":
json.NewDecoder(r.Body).Decode(user)
json.NewEncoder(w).Encode(user)
case "DELETE":
// 删除用户
for i := range users {
if users[i].ID == id {
users = append(users[:i], users[i+1:]...)
break
}
}
w.WriteHeader(http.StatusNoContent)
default:
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
package main
import (
"fmt"
"net/http"
"time"
)
// 日志中间件
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))
})
}
// 认证中间件
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, "未授权", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
// 应用中间件
handler := loggingMiddleware(mux)
http.ListenAndServe(":8080", handler)
}
package main
import (
"fmt"
"net/http"
"time"
)
type Middleware func(http.Handler) http.Handler
func chain(h http.Handler, middlewares ...Middleware) http.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
h = middlewares[i](h)
}
return h
}
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))
})
}
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == "OPTIONS" {
return
}
next.ServeHTTP(w, r)
})
}
func recoverMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
http.Error(w, "服务器内部错误", http.StatusInternalServerError)
fmt.Printf("Panic: %v\n", err)
}
}()
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
// 应用中间件链
handler := chain(mux, loggingMiddleware, corsMiddleware, recoverMiddleware)
http.ListenAndServe(":8080", handler)
}
package main
import (
"net/http"
)
func main() {
// 方式1:使用 http.FileServer
fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
// 方式2:使用 http.ServeFile
http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./files/document.pdf")
})
// 方式3:自定义文件服务器
http.HandleFunc("/files", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Disposition", "attachment; filename=document.pdf")
http.ServeFile(w, r, "./files/document.pdf")
})
http.ListenAndServe(":8080", nil)
}
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "HTTPS 安全连接")
})
// 使用证书文件启动 HTTPS
err := http.ListenAndServeTLS(
":443",
"server.crt",
"server.key",
nil,
)
if err != nil {
fmt.Println("启动失败:", err)
}
}
package main
import (
"fmt"
"net/http"
)
func main() {
// HTTP 重定向到 HTTPS
go func() {
http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
target := "https://" + r.Host + r.URL.Path
http.Redirect(w, r, target, http.StatusMovedPermanently)
}))
}()
// HTTPS 服务器
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "HTTPS 安全连接")
})
http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
}
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second) // 模拟耗时操作
fmt.Fprintf(w, "Hello, World!")
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// 启动服务器
go func() {
fmt.Println("服务器启动在 :8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("服务器错误: %v\n", err)
}
}()
// 监听系统信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
fmt.Println("正在关闭服务器...")
// 优雅关闭
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
fmt.Printf("服务器强制关闭: %v\n", err)
}
fmt.Println("服务器已关闭")
}
package main
import (
"net/http"
"time"
)
func main() {
server := &http.Server{
Addr: ":8080",
Handler: nil,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
MaxHeaderBytes: 1 << 20, // 1 MB
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
server.ListenAndServe()
}
本章详细介绍了 Go 语言的 HTTP 服务器编程:
http.HandleFunc 和 http.ListenAndServehttp.ServeMux 和 RESTful API 设计http.FileServer 提供静态文件服务server.Shutdown 优雅关闭服务器HTTP 服务器是 Go 语言最常用的功能之一,掌握它能让你快速构建 Web 服务。在下一章中,我们将学习 TCP 和 UDP 编程。