英文:
How do I split URLS in multiple Files using gorilla/mux?
问题
我的目录结构如下:
myapp/
|
+-- moduleX
| |
| +-- views.go
|
+-- start.go
应用程序通过start.go
启动,然后我在那里配置所有的路由,并从moduleX/views.go
导入处理程序,代码如下:
package main
import (
"net/http"
"github.com/gorilla/mux"
"myapp/moduleX"
)
func main() {
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
r.HandleFunc("/", moduleX.SomePostHandler).Methods("POST")
r.HandleFunc("/", moduleX.SomeHandler)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
现在我想添加更多的模块,并且想知道是否(以及如何)可以在urls.go
文件中定义模块的URL,并在start.go
中以一次导入或某种module.GetURLs
函数的方式让start.go
知道所有somemodule/urls.go
文件中的URL。
英文:
My directory structure looks like this:
myapp/
|
+-- moduleX
| |
| +-- views.go
|
+-- start.go
The app gets started with start.go
and from there I configure all the routes and import the handlers from moduleX/views.go
like this:
package main
import (
"net/http"
"github.com/gorilla/mux"
"myapp/moduleX"
)
func main() {
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
r.HandleFunc("/", moduleX.SomePostHandler).Methods("POST")
r.HandleFunc("/", moduleX.SomeHandler)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
Now I want to add more modules and ask myself if (and how) it is possible to define the urls in the module in a urls.go
file and somehow "import" them in start.go
. Specifically I want start.go
to know all the URLs in all the somemodule/urls.go
files with just one import or some kind of a module.GetURLs
function.
答案1
得分: 4
为什么不让处理程序自己插入到路由表中呢?
如果你在每个处理程序的单独go文件中定义,可以使用每个文件的init()
函数将处理程序添加到全局路由表中。
所以可以这样做:
main.go:
type route{
method string
path string
handler func(w http.ResponseWriter, r *http.Request)
}
var routes = make([]route,0)
func registerRoute(r route){
routes = append(routes,r)
}
func server(){
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
// 设置所有注册的路由
for _, rt = range(routes){
r.HandleFunc(rt.path,rt.handler).Methods(rt.Method)
}
// 这里通常还有其他需要添加的内容
// 最后在这里启动服务器!
http.ListenAndServe(":8080", nil)
}
yourmodule.go:
func init(){
r = route{
method="GET",
path="/yourmodule/path/whatever",
handler=yourHandlerFunc,
}
registerRoute(r)
}
func yourHandlerFunc(w http.ResponseWriter, r *http.Request){
// 在这里进行一些很棒的网页处理
}
init()
函数会在包的每个文件执行之前调用,因此您可以确保在启动服务器之前所有处理程序都已注册。
这种模式可以扩展,以允许根据需要进行更多的注册操作,因为模块本身现在负责自己的注册,而不是试图将所有特殊情况都塞进一个注册函数中。
英文:
<p>Why not get the handlers to insert themselves into the routes table?</p>
<p>If you're defining each handler in its own go file, use the init()
func for each file to add the handler to a global routing table</p>
<p>So something like:</p>
main.go:
type route{
method string
path string
handler func(w http.ResponseWriter, r *http.Request)
}
var routes = make([]route,0)
func registerRoute(r route){
routes = append(routes,r)
}
func server(){
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
// set up all the registered routes
for _, rt = range(routes){
r.HandleFunc(rt.path,rt.handler).Methods(rt.Method)
}
// and there's usually some other stuff that needs to go in here
//before we finally serve the content here!
http.ListenAndServe(":8080", nil)
}
yourmodule.go:
func init(){
r = route{
method="GET",
path="/yourmodule/path/whatever",
handler=yourHandlerFunc,
}
registerRoute(r)
}
func yourHandlerFunc(w http.ResponseWriter, r *http.Request){
//awesome web stuff goes here
}
<p>init() gets called for each file in a package before execution of the package main() so you can be sure that all your handlers will be registered before you kick the server off.</p><p>This pattern can be extended to allow for more tricksy registration gubbins to happen as needed, since the modules themselves are now in charge of their own registration, instead of trying to cram all the special cases into one registration func</p>
答案2
得分: 3
要一次性创建一组mux.Route
,你可以定义一个自定义类型(在下面的示例中为handler
),然后进行如下操作:
package main
import (
"fmt"
"github.com/gorilla/mux"
"net/http"
)
type handler struct {
path string
f http.HandlerFunc
methods []string
}
func makeHandlers(hs []handler, r *mux.Router) {
for _, h := range hs {
if len(h.methods) == 0 {
r.HandleFunc(h.path, h.f)
} else {
r.HandleFunc(h.path, h.f).Methods(h.methods...)
}
}
}
// 创建一些示例处理函数
func somePostHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "POST Handler")
}
func someHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Normal Handler")
}
func main() {
// 定义一些处理程序
handlers := []handler{{path: "/", f: somePostHandler, methods: []string{"POST"}}, {path: "/", f: someHandler}}
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
// 初始化处理程序
makeHandlers(handlers, r)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
英文:
EDIT:
To create a group of mux.Route
's in one go, you could define a custom type (handler
in the example below) and do do something like:
package main
import (
"fmt"
"github.com/gorilla/mux"
"net/http"
)
type handler struct {
path string
f http.HandlerFunc
methods []string
}
func makeHandlers(hs []handler, r *mux.Router) {
for _, h := range hs {
if len(h.methods) == 0 {
r.HandleFunc(h.path, h.f)
} else {
r.HandleFunc(h.path, h.f).Methods(h.methods...)
}
}
}
// create some example handler functions
func somePostHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "POST Handler")
}
func someHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Normal Handler")
}
func main() {
//define some handlers
handlers := []handler{{path: "/", f: somePostHandler, methods: []string{"POST"}}, {path: "/", f: someHandler}}
r := mux.NewRouter()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./templates/static/"))))
// Initialise the handlers
makeHandlers(handlers, r)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
ORIGINAL ANSWER:
You don't need to import
them if they're in the same package.
You can define the URL variables in urls.go
, and then the logic in views.go
(or another file in package moduleX
) as long as they have the same package
declaration.
For instance:
// moduleX/urls.go
package moduleX
var (
urls = []string{"http://google.com/", "http://stackoverflow.com/"}
)
Then:
// moduleX/views.go (or some other file in package moduleX)
package moduleX
func GetUrls() []string {
return urls
}
Then:
// start.go
package main
import (
"fmt"
"myapp/moduleX"
)
func main() {
for _, url := range moduleX.GetUrls() {
fmt.Println(url)
}
}
Or, even easier, just export the variable from the moduleX
package by giving it a capitalised name.
For instance:
// moduleX/urls.go
package moduleX
var URLs = []string{"http://google.com/", "http://stackoverflow.com/"}
and then:
// start.go
package main
import (
"fmt"
"myapp/moduleX"
)
func main() {
for _, url := range moduleX.URLs {
fmt.Println(url)
}
}
Have a look at any of the Go source to see how they handle the same problem. A good example is in the SHA512
source where the lengthy variable is stored in sha512block.go
and the logic is in sha512.go
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论