我是 Golang 的新手,需要帮助。我正试图在没有ORM的情况下创建REST API Web服务。
现在,我已成功连接到 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 / factors.go :
package models
type Factor struct {
ID int `json:"id"`
Name string `json:"name"`
}
GetFactors
控制器的外观如何正确?有人可以告诉我。例如,我将db
对象传递给GetFactors
控制器,如下例所示。不幸的是,这似乎是不正确的。
controllers / factors.go :
func GetFactors(db *sql.DB, w http.ResponseWriter, req *http.Request) {
// some code
}
configurations / 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
}
答案 0 :(得分:2)
没有正确的方法,它主要基于意见。
HandlerFunc函数的语义应该类似于func(w http.ResponseWriter, r *http.Request)
,为了传递数据库,您可以使用闭包,这是一个示例。
// ... some code here
subrouter.HandleFunc("/factors", controllers.GetFactors(db)).Methods("GET")
// ... some code here
func GetFactors(db *sql.DB) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// some code
})
}
另一个选择:
对此我不太确定,但是您可以根据需要进行调整。初始化Controller
结构并将db传递给它:
// ... 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结构上的方法。 在控制器中定义一个结构
type Controller struct {
DB *PostgreSQLDatabase
}
func (c Controller) GetFactors(w http.ResponseWriter, req *http.Request) {
// some code
// c.DB.MySqlMethod()
}
答案 1 :(得分:1)
您的功能GetFactors
必须看起来像:
func GetFactors(w http.ResponseWriter, r *http.Request) {}
在主文件中必须具有:
subrouter.HandleFunc("/factors", controllers.GetFactors).Methods("GET")
为了获得数据库连接,您必须在软件包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
}
答案 2 :(得分:1)
我要使用的一种模式是定义自己的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))
}
希望这会有所帮助。