接口开发
RESTful API设计
使用Go实现RESTful API的最佳实践。
package main
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
)
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"-"` // 不在JSON中显示
}
// 创建用户
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 处理用户创建...
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
// 获取用户列表
func getUsers(w http.ResponseWriter, r *http.Request) {
users := []User{
{ID: "1", Name: "John", Email: "john@example.com"},
{ID: "2", Name: "Jane", Email: "jane@example.com"},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
// 获取单个用户
func getUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// 查找用户...
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(User{ID: id, Name: "John", Email: "john@example.com"})
}
// 更新用户
func updateUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
user.ID = id
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
// 删除用户
func deleteUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// 删除用户...
w.WriteHeader(http.StatusNoContent)
}
func main() {
r := mux.NewRouter()
// 注册路由
r.HandleFunc("/users", createUser).Methods("POST")
r.HandleFunc("/users", getUsers).Methods("GET")
r.HandleFunc("/users/{id}", getUser).Methods("GET")
r.HandleFunc("/users/{id}", updateUser).Methods("PUT")
r.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")
http.ListenAndServe(":8080", r)
}
API版本控制
实现API版本控制的最佳实践。
package main
import (
"net/http"
"github.com/gorilla/mux"
)
func v1Handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("API v1"))
}
func v2Handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("API v2"))
}
func main() {
r := mux.NewRouter()
// 版本1路由
v1 := r.PathPrefix("/v1").Subrouter()
v1.HandleFunc("/users", v1Handler)
// 版本2路由
v2 := r.PathPrefix("/v2").Subrouter()
v2.HandleFunc("/users", v2Handler)
http.ListenAndServe(":8080", r)
}
API文档
使用Swagger生成API文档。
package main
import (
"github.com/swaggo/http-swagger"
"github.com/swaggo/swag"
)
// @title User API
// @version 1.0
// @description This is a sample user API
// @host localhost:8080
// @BasePath /api/v1
// @tag.name Users
// @tag.description User management operations
// @route POST /users
// @summary Create a new user
// @description Create a new user with the provided information
// @tags Users
// @accept json
// @produce json
// @param user body User true "User object"
// @success 201 {object} User
// @failure 400 {object} ErrorResponse
// @router /users [post]
func createUser(w http.ResponseWriter, r *http.Request) {
// 实现代码...
}
func main() {
r := mux.NewRouter()
// 注册Swagger文档
r.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler)
http.ListenAndServe(":8080", r)
}
API认证
实现API认证和授权。
package main
import (
"net/http"
"github.com/dgrijalva/jwt-go"
)
type Claims struct {
UserID string `json:"user_id"`
jwt.StandardClaims
}
func generateToken(userID string) (string, error) {
claims := &Claims{
UserID: userID,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte("your-secret-key"))
}
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return []byte("your-secret-key"), nil
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
}
}
func main() {
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// 处理登录...
token, _ := generateToken("user123")
w.Write([]byte(token))
})
http.HandleFunc("/protected", authMiddleware(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Protected resource"))
}))
http.ListenAndServe(":8080", nil)
}
API限流
实现API请求限流。
package main
import (
"net/http"
"sync"
"time"
)
type RateLimiter struct {
requests map[string][]time.Time
mu sync.Mutex
limit int
window time.Duration
}
func NewRateLimiter(limit int, window time.Duration) *RateLimiter {
return &RateLimiter{
requests: make(map[string][]time.Time),
limit: limit,
window: window,
}
}
func (rl *RateLimiter) Allow(ip string) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
windowStart := now.Add(-rl.window)
// 清理过期的请求记录
validRequests := make([]time.Time, 0)
for _, t := range rl.requests[ip] {
if t.After(windowStart) {
validRequests = append(validRequests, t)
}
}
if len(validRequests) >= rl.limit {
return false
}
validRequests = append(validRequests, now)
rl.requests[ip] = validRequests
return true
}
func rateLimitMiddleware(limiter *RateLimiter) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip := r.RemoteAddr
if !limiter.Allow(ip) {
http.Error(w, "Too many requests", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
}
func main() {
limiter := NewRateLimiter(100, time.Minute)
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
handler := rateLimitMiddleware(limiter)(mux)
http.ListenAndServe(":8080", handler)
}