以易于理解和扩展的方式组织代码。常见的结构包括将代码分为模型、处理程序、路由、中间件、实用程序和配置等文件夹。
结构示例:
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) }
使用中间件进行日志记录、身份验证和其他横切关注点。
中间件/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 等结构化日志库来获得更好的日志记录。
中间件/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。
以上是Rest Full API - Golang(最佳实践)的详细内容。更多信息请关注PHP中文网其他相关文章!