英文:
Registering Routes to Central Object in Go
问题
我正在开发一个简单的Go REST API,使用Mux库。大部分教程都建议按照以下方式创建路由器:
- 一个
routes.go
文件,其中包含一个全局数组,包含所有的路由和路由处理函数。 - 一个
router.go
文件,创建一个路由器对象,并循环遍历全局数组,将所有路由注册到路由器中。
我更愿意使用另一种模式:
- 一个
router.go
文件实例化一个路由器对象,并拥有一个RegisterRoute
函数。 - 每个文件代表API的不同对象或组件,可以调用
RegisterRoute
函数,并向路由器添加额外的路由。
我不知道如何做到这一点,因为它似乎需要为每个文件创建一个初始化函数,并从main()
函数中调用它(这违背了初衷)。有没有一种被广泛接受的方法来实现这个?
英文:
I'm working on a simple Go REST API, using Mux. Most of the tutorials I've found suggested creating the router as follows:
- A
routes.go
file which contains a global array of all routes and all route handlers. - A
router.go
file which creates a router object and loops over the global array and registers everything to the router.
I'd rather use a different model:
- A
router.go
file instantiates a router object and has aRegisterRoute
function - Each file, representing a different object or component of the API, can call
RegisterRoute
and add additional routes to the router.
I have no idea how to do this, because it seems to require creating an initialization function for each file and calling it from main()
(which defeats the purpose). Is there any accepted way to do this?
答案1
得分: 8
你可以使用func init()
。这是一个特殊的函数,在程序执行之前、包初始化期间被调用。
以下是使用gorilla/mux路由器实现你想要的功能的示例,尽管也可以使用其他任何mux库来实现。
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
// main.go
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
var routes []Route
func registerRoute(route Route) {
routes = append(routes, route)
}
func main() {
router := mux.NewRouter().StrictSlash(false)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatalln(err)
}
}
// index.go
func init() {
registerRoute(Route{
"index",
"GET",
"/",
func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "welcome")
},
})
}
// users.go
func init() {
registerRoute(Route{
"listUsers",
"GET",
"/users",
listUsers,
})
}
func listUsers(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "users list")
}
// products.go
func init() {
registerRoute(Route{
"listProducts",
"GET",
"/products",
listProducts,
})
}
func listProducts(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "products list")
}
这种模式在Go语言中被database/sql
和image
等包使用。你可以在这里阅读更多相关信息:https://www.calhoun.io/why-we-import-packages-we-dont-actually-use-in-golang/
英文:
You can use func init()
. It is a special function which is called right before program execution, during package initialization.
Here is an example of how to achieve what you want using gorilla/mux router, though it can be achieved with any other mux library.
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
// main.go
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
var routes []Route
func registerRoute(route Route) {
routes = append(routes, route)
}
func main() {
router := mux.NewRouter().StrictSlash(false)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatalln(err)
}
}
// index.go
func init() {
registerRoute(Route{
"index",
"GET",
"/",
func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "welcome")
},
})
}
// users.go
func init() {
registerRoute(Route{
"listUsers",
"GET",
"/users",
listUsers,
})
}
func listUsers(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "users list")
}
// products.go
func init() {
registerRoute(Route{
"listProducts",
"GET",
"/products",
listProducts,
})
}
func listProducts(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "products list")
}
This pattern is used by golang for example by database/sql
and image
packages. You can read a little bit more about this here: https://www.calhoun.io/why-we-import-packages-we-dont-actually-use-in-golang/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论