首頁  >  文章  >  後端開發  >  Rest Full API - Golang(最佳實踐)

Rest Full API - Golang(最佳實踐)

王林
王林原創
2024-07-28 07:09:43902瀏覽

Rest Full API - Golang (Best Practices)

一、項目結構

以易於理解和擴展的方式組織程式碼。常見的結構包括將程式碼分為模型、處理程序、路由、中間件、實用程式和配置等資料夾。

結構範例:

go-rest-api/
|-- main.go
|-- config/
|   |-- config.go
|-- handlers/
|   |-- user.go
|-- models/
|   |-- user.go
|-- routes/
|   |-- routes.go
|-- middlewares/
|   |-- logging.go
|-- utils/
|   |-- helpers.go

2. 環境配置

將設定設定(如資料庫憑證、連接埠號碼等)儲存在環境變數或設定檔中。使用像 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)
    }
}

3. 錯誤處理

始終適當地處理錯誤。傳回有意義的錯誤訊息和 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)
}

4. 中介軟體

使用中間件進行日誌記錄、驗證和其他橫切關注點。

中介軟體/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)

5.JSON處理

使用正確的 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)
}

6. 資料庫訪問

使用資料庫來儲存您的資料。使用 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))
}

7. 日誌記錄

使用 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")
    })
}

8. 安全

透過使用 HTTPS、驗證和清理輸入以及實作適當的驗證和授權,確保您的 API 安全。

9. 版本控制

對 API 進行版本控制以在不破壞現有客戶端的情況下處理變更。這可以透過在 URL 中包含版本來完成,例如 /api/v1/users。

10. 文檔

使用 Swagger 或 Postman 等工具記錄您的 API,為開發人員提供清晰的使用說明。

遵循這些最佳實踐,您可以在 Go 中建立健壯、可維護且可擴展的 RESTful API。

以上是Rest Full API - Golang(最佳實踐)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn