以易於理解和擴展的方式組織程式碼。常見的結構包括將程式碼分為模型、處理程序、路由、中間件、實用程式和配置等資料夾。
架構範例:
go-rest-api/ |-- main.go |-- config/ | |-- config.go |-- handlers/ | |-- user.go |-- models/ | |-- user.go |-- routes/ | |-- routes.go |-- middlewares/ | |-- logging.go |-- utils/ | |-- helpers.go
將設定設定(如資料庫憑證、連接埠號碼等)儲存在環境變數或設定檔中。使用像 viper 這樣的套件來管理配置。
config/config.go:
package config import ( "github.com/spf13/viper" "log" ) type Config struct { Port string DB struct { Host string Port string User string Password string Name string } } var AppConfig Config func LoadConfig() { viper.SetConfigName("config") viper.AddConfigPath(".") viper.AutomaticEnv() if err := viper.ReadInConfig(); err != nil { log.Fatalf("Error reading config file, %s", err) } err := viper.Unmarshal(&AppConfig) if err != nil { log.Fatalf("Unable to decode into struct, %v", err) } }
始終適當地處理錯誤。傳回有意義的錯誤訊息和 HTTP 狀態碼。
handlers/user.go:
func GetUserHandler(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) id, err := strconv.Atoi(params["id"]) if err != nil { http.Error(w, "Invalid user ID", http.StatusBadRequest) return } user, err := findUserByID(id) if err != nil { http.Error(w, "User not found", http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(user) }
使用中間件進行日誌記錄、驗證和其他橫切關注點。
middlewares/logging.go:
package middlewares import ( "log" "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) log.Printf("%s %s %s", r.Method, r.RequestURI, time.Since(start)) }) }
在main.go或routes/routes.go中:
r.Use(middlewares.LoggingMiddleware)
使用正確的 JSON 編碼和解碼。驗證傳入的 JSON 資料以確保其符合預期結構。
handlers/user.go:
func CreateUserHandler(w http.ResponseWriter, r *http.Request) { var user models.User if err := json.NewDecoder(r.Body).Decode(&user); err != nil { http.Error(w, "Invalid input", http.StatusBadRequest) return } // Validate user data... users = append(users, user) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(user) }
使用資料庫來儲存您的資料。使用 gorm 等套件進行 ORM 或使用 sqlx 進行原始 SQL 查詢。
models/user.go:
package models import "gorm.io/gorm" type User struct { gorm.Model Name string `json:"name"` Email string `json:"email"` }
main.go:
package main import ( "github.com/yourusername/go-rest-api/config" "github.com/yourusername/go-rest-api/routes" "gorm.io/driver/postgres" "gorm.io/gorm" "log" "net/http" ) func main() { config.LoadConfig() dsn := "host=" config.AppConfig.DB.Host " user=" config.AppConfig.DB.User " password=" config.AppConfig.DB.Password " dbname=" config.AppConfig.DB.Name " port=" config.AppConfig.DB.Port " sslmode=disable" db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { log.Fatalf("Could not connect to the database: %v", err) } r := routes.NewRouter(db) log.Println("Starting server on port", config.AppConfig.Port) log.Fatal(http.ListenAndServe(":" config.AppConfig.Port, r)) }
使用 logrus 或 zap 等結構化日誌庫來獲得更好的日誌記錄。
middlewares/logging.go:
package middlewares import ( "github.com/sirupsen/logrus" "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) logrus.WithFields(logrus.Fields{ "method": r.Method, "url": r.URL.Path, "time": time.Since(start), }).Info("handled request") }) }
透過使用 HTTPS、驗證和清理輸入以及實施適當的身份驗證和授權,確保您的 API 安全。
對 API 進行版本控制以在不破壞現有客戶端的情況下處理變更。這可以透過在 URL 中包含版本來完成,例如 /api/v1/users.
使用 Swagger 或 Postman 等工具記錄您的 API,為開發人員提供清晰的使用說明。
透過遵循這些最佳實踐,您可以在 Go 中建立健全、可維護且可擴展的 RESTful API。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3