Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确地将控制器设置为Golang中的路线?_Go - Fatal编程技术网

如何正确地将控制器设置为Golang中的路线?

如何正确地将控制器设置为Golang中的路线?,go,Go,我刚来戈兰,需要一些帮助。我正在尝试创建没有ORM的RESTAPI web服务 现在我已成功连接到PostgreSQL数据库。在数据库中,我有一个叫做“因子”的表。我想创建CRUD操作。问题在于控制器的逻辑 main.go: 模型/因子.go: GetFactors控制器的外观是否正确?有人能给我看看吗。例如,我将db对象传递给GetFactors控制器,如下例所示。不幸的是,这似乎是不正确的 控制器/因子.go: 配置/PostgreSQL.go: 您的func GetFactors必须如下所

我刚来戈兰,需要一些帮助。我正在尝试创建没有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))
}