쉽게 이해하고 확장할 수 있는 방식으로 코드를 구성하세요. 일반적인 구조에는 코드를 모델, 핸들러, 경로, 미들웨어, 유틸리티 및 구성과 같은 폴더로 분리하는 것이 포함됩니다.
구조 예:
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) }
데이터베이스를 사용하여 데이터를 저장하세요. ORM에는 gorm, 원시 SQL 쿼리에는 sqlx와 같은 패키지를 사용하세요.
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 버전을 지정하세요. /api/v1/users.
와 같이 URL에 버전을 포함하면 됩니다.Swagger 또는 Postman과 같은 도구를 사용하여 API를 문서화하여 개발자에게 명확한 사용 지침을 제공하세요.
이러한 모범 사례를 따르면 Go에서 강력하고 유지 관리 및 확장 가능한 RESTful API를 만들 수 있습니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3