如何正确地将控制器设置为Golang中的路线?
我刚来戈兰,需要一些帮助。我正在尝试创建没有ORM的RESTAPI web服务 现在我已成功连接到PostgreSQL数据库。在数据库中,我有一个叫做“因子”的表。我想创建CRUD操作。问题在于控制器的逻辑 main.go: 模型/因子.go: GetFactors控制器的外观是否正确?有人能给我看看吗。例如,我将db对象传递给GetFactors控制器,如下例所示。不幸的是,这似乎是不正确的 控制器/因子.go: 配置/PostgreSQL.go: 您的func GetFactors必须如下所示:如何正确地将控制器设置为Golang中的路线?,go,Go,我刚来戈兰,需要一些帮助。我正在尝试创建没有ORM的RESTAPI web服务 现在我已成功连接到PostgreSQL数据库。在数据库中,我有一个叫做“因子”的表。我想创建CRUD操作。问题在于控制器的逻辑 main.go: 模型/因子.go: GetFactors控制器的外观是否正确?有人能给我看看吗。例如,我将db对象传递给GetFactors控制器,如下例所示。不幸的是,这似乎是不正确的 控制器/因子.go: 配置/PostgreSQL.go: 您的func GetFactors必须如下所
func GetFactors(w http.ResponseWriter, r *http.Request) {}
在主文件中,您必须具有:
subrouter.HandleFunc("/factors", controllers.GetFactors).Methods("GET")
为了获得DB连接,您必须在包rest\U api/配置中具有类似于GetDB的func
在rest_api/配置中,您必须具有以下内容:
var db *PostgreSQLDatabase
func init() {
var err error
db, err = configurations.PostgreSQLDatabase()
if err != nil {
log.Fatal(err)
}
}
func GetDB() *PostgreSQLDatabase {
return db
}
没有正确的方法,主要是基于意见 HandlerFunc函数的语义应该类似于funcw http.ResponseWriter,r*http.Request,为了传递数据库,可以使用闭包,下面是一个示例 梅因,加油 控制器/因子.go 另一种选择: 我对此不太确定,但你可以根据自己的需要加以调整。初始化控制器结构并将db传递给它: 梅因,加油 表示控制器结构上的方法。 在控制器中定义一个结构 控制器/因子.go
我喜欢使用的一种模式是定义您自己的路由器结构,该结构将mux.Router作为字段,并封装数据库连接、应用程序配置等内容 我发现这样做可以在需要不同资源和开发收益时轻松更新您的路线 首先创建一个路由器对象,该对象在创建时接收数据库连接,并使其可用于您希望使用的所有路由 路由器,开始 然后在main.go中,您可以简单地创建自定义路由器,并将其传递给数据库连接。然后可以将自定义路由器直接传递给ListendServe 梅因,加油
希望这能有所帮助。您好!谢谢你的回答。你能再查一下我的帖子吗?!我认为我的PostgreSQLDatabase函数和你的GetDB函数很接近。它们都返回数据库对象。如果要在GetFactors控制器内运行SQL查询,是否需要将数据库对象传递给该控制器以执行SQL查询?不是吗?从您的代码中不清楚如何在GetFactors controller内进行sql查询。funcs PostgreSQLDatabase和GetDB必须分开。在返回db之前的PostgreSQLDatabase中,nil您已经将db值分配给包中的db var,并从func GetDB返回此值。好的,我将把它们分开,没问题。下一步是什么?我将在GetFactors控制器中调用GetDB函数,对吗?我不清楚GetFactors控制器中会有什么…您好!谢谢你的回答。我不确定这是我努力做的最佳实践。如您所见,我将数据库对象传递给GetFactors函数。我只完成了一项任务。我想在GetFactors控制器内运行SQL查询。你认为我想做的正确吗?或者你可以建议更优雅的方式?我认为这是一个很好的设计,因为它可以避免声明全局变量。在这种情况下,还有另一个选项,你可以用数据库定义一个结构并在该方法上声明GetFactors。不幸的是,我不清楚你的另一个选项。你能给我举个小例子吗?你好!谢谢你的回答。我认为你建议的是更结构化的方式。我还有一个问题。假设我想把GetFactors函数放在一个单独的文件中。我需要如何传递Router.go文件中的Router struct?!通常,我会将路由器结构及其方法(即GetFactors)放入自己的路由器包中。然后,您可以将它们放在单独的文件中,只要它们在文件顶部具有相同的包名。由于GetFactors将Router结构作为其接收器,因此不需要显式地将其传递给GetFactors。将来,对于每个路由,Router.go文件中的函数太多。它会膨胀的。我不想把所有的东西都放在一个文件里。假设我创建控制器文件夹包控制器。在该文件夹中创建factors.go文件并放入下一个代码:func r*路由器GetFactorsw http.ResponseWriter,req*http.Request{}Golang看不到r*路由器结构。不知道如何解决这个问题。Router和GetFactors需要在同一个包中,但不需要在同一个文件中。创建一个controllers文件夹,然后在该文件夹中创建一个router.go和一个factors.go文件,每个文件的顶部都有包控制器,然后GetFactors可以看到路由器,但不需要在同一个文件中。
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
}
func GetFactors(w http.ResponseWriter, r *http.Request) {}
subrouter.HandleFunc("/factors", controllers.GetFactors).Methods("GET")
var db *PostgreSQLDatabase
func init() {
var err error
db, err = configurations.PostgreSQLDatabase()
if err != nil {
log.Fatal(err)
}
}
func GetDB() *PostgreSQLDatabase {
return db
}
// ... 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
})
}
// ... 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
type Controller struct {
DB *PostgreSQLDatabase
}
func (c Controller) GetFactors(w http.ResponseWriter, req *http.Request) {
// some code
// c.DB.MySqlMethod()
}
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)
}
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))
}