Как правильно составить контроллеры для маршрутов в Голанге? - PullRequest
0 голосов
/ 25 февраля 2019

Я новичок в Голанге и мне нужна помощь.Я пытаюсь создать веб-сервис REST API без ORM.

Сейчас я успешно подключен к базе данных PostgreSQL .В базе данных у меня есть таблица, которая называется factors.Я хочу создавать операции CRUD.Проблема в логике контроллеров.

main.go :

package main

import (
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "rest_api/configurations"
    "rest_api/controllers"
)

func main()  {
    db, err := configurations.PostgreSQLDatabase()
    if err != nil {
        log.Fatal(err)
    }

    router := mux.NewRouter()

    router.StrictSlash(true)

    subrouter := router.PathPrefix("/api").Subrouter()

    subrouter.HandleFunc("/factors", controllers.GetFactors(db)).Methods("GET")

    log.Fatal(http.ListenAndServe(":8000", router))
}

models / factor.go :

package models

type Factor struct {
    ID int `json:"id"`
    Name string `json:"name"`
}

Как правильно выглядит контроллер GetFactors?Может кто-нибудь показать мне, пожалуйста.Например, я передаю объект db контроллеру GetFactors, как в примере ниже.К сожалению, похоже, что это неверно.

controllers / factor.go :

func GetFactors(db *sql.DB, w http.ResponseWriter, req *http.Request) {
    // some code
}

конфигурации / PostgreSQL.go :

func PostgreSQLDatabase() (*sql.DB, error) {
    // Load environment variables from ".env" file.
    err := godotenv.Load(".env")
    if err != nil {
        log.Fatal(err)
    }

    // Initialize database-related variables.
    dbUser := os.Getenv("PostgreSQL_USER")
    dbPassword := os.Getenv("PostgreSQL_PASSWORD")
    dbHost := os.Getenv("PostgreSQL_HOST")
    dbName := os.Getenv("PostgreSQL_DB_NAME")
    dbURL := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable", dbUser, dbPassword, dbHost, dbName)

    // Create PostgreSQL database connection pool.
    db, err := sql.Open("postgres", dbURL)
    if err != nil {
        return nil, err
    }

    // Ping PostgreSQL database to make sure it's alive.
    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    } else {
        log.Println("Web service successfully connected to remote PostgreSQL database.")
    }

    return db, nil
}

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Правильного пути нет, в основном это мнение.

Семантика функции HandlerFunc должна быть похожа на func(w http.ResponseWriter, r *http.Request), для передачи базы данных вы можете использовать замыкания, вот пример.

main.go

// ... some code here 
subrouter.HandleFunc("/factors", controllers.GetFactors(db)).Methods("GET")
// ... some code here

controllers / factor.go

func GetFactors(db *sql.DB) http.HandlerFunc {
  return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    // some code
  })
}

Другой вариант:

Я не совсем уверен в этом, но вы можете адаптировать его к вашим потребностям.Инициализируйте структуру Controller и передайте в нее db:

main.go

// ... some code here 
db, err := configurations.PostgreSQLDatabase()
if err != nil {
    log.Fatal(err)
}
ctrl := controllers.Controller{DB: db}
subrouter.HandleFunc("/factors", ctrl.GetFactors).Methods("GET")
// ... some code here

Обозначьте метод в структуре Controller.Определите структуру в контроллерах

controllers / factor.go

type Controller struct {
  DB *PostgreSQLDatabase
}

func (c Controller) GetFactors(w http.ResponseWriter, req *http.Request) {
    // some code
    // c.DB.MySqlMethod()
}
0 голосов
/ 25 февраля 2019

Шаблон, который мне нравится использовать, - это определить собственную структуру Router, которая имеет mux.Router в качестве поля, а также инкапсулирует такие вещи, как подключение к базе данных, конфигурация приложения и т. Д.

Я считаюэто позволяет легко обновлять ваши маршруты, когда им требуются разные ресурсы и процессы разработки.

Сначала создайте объект-маршрутизатор, который принимает соединение с базой данных при создании и делает его доступным для всех маршрутов, которые вы хотите использовать.

router.go

package main

import (
    "net/http"
    "database/sql"

    "github.com/gorilla/mux"
)

type Router struct {
    router *mux.Router
    db *sql.DB
}

func NewRouter(db *sql.DB) (*Router, error) {
    router := mux.NewRouter()
    router.StrictSlash(true)
    subrouter := router.PathPrefix("/api").Subrouter()

    r := &Router{
        router: router,
        db: db,
    }

    subrouter.HandleFunc("/factors", r.GetFactors).Methods(http.MethodGet)

    return r, nil
}

func (r *Router) GetFactors(w http.ResponseWriter, req *http.Request) {
    // Now you can access your database via `r.db`
}

// Needed so we can pass our custom router to ListenAndServe.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    r.router.ServeHTTP(w, req)
}

Затем в main.go вы можете просто создать свой собственный маршрутизатор, передав ему соединение с базой данных.Затем пользовательский маршрутизатор может быть напрямую передан ListenAndServe.

main.go

package main

import (
    "log"
    "net/http"
    "rest_api/configurations"
    "rest_api/controllers"
)

func main()  {
    db, err := configurations.PostgreSQLDatabase()
    if err != nil {
        log.Fatal(err)
    }

    router, err := NewRouter(db)
    if err != nil {
        log.Fatalf("error initializing router: %v", err)
    }

    log.Fatal(http.ListenAndServe(":8000", router))
}

Надеюсь, это поможет.

0 голосов
/ 25 февраля 2019

Ваш func GetFactors должен выглядеть следующим образом:

func GetFactors(w http.ResponseWriter, r *http.Request) {}

, а в основном файле вы должны иметь:

subrouter.HandleFunc("/factors", controllers.GetFactors).Methods("GET")

, и для получения соединения с БД у вас должен быть func какGetDB в вашем пакете "rest_api/configurations".

В "rest_api/configurations" у вас должно быть что-то вроде:

var db *PostgreSQLDatabase

func init() {
    var err error
    db, err = configurations.PostgreSQLDatabase()
    if err != nil {
        log.Fatal(err)
    }
}

func GetDB() *PostgreSQLDatabase {
  return db
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...