如何使用gorilla / mux在多个文件中拆分URL?

时间:2013-10-14 08:53:53

标签: url go 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中“导入”它们。具体来说,我希望start.go知道所有somemodule/urls.go文件中的所有网址,只需一次导入或某种module.GetURLs功能。

2 个答案:

答案 0 :(得分:4)

为什么不让处理程序将自己插入到路由表中?

如果您在自己的go文件中定义每个处理程序,请对每个文件使用`init()`func将处理程序添加到全局路由表

类似于:


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
}

在执行包main()之前,会为包中的每个文件调用init(),这样您就可以确保在关闭服务器之前注册所有处理程序。

这个模式可以扩展到允许更多特技注册gubbins根据需要发生,因为模块本身现在负责自己的注册,而不是试图将所有特殊情况塞进一个注册函数

答案 1 :(得分: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...)
        }
    }
}

// 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)
}

Playground

原始回答:

如果他们在same package中,则您无需import

您可以在urls.go中定义网址变量,然后在views.go(或package moduleX中的其他文件)中定义逻辑,只要它们具有相同的package声明即可

例如:

// moduleX/urls.go

package moduleX

var (
    urls = []string{"http://google.com/", "http://stackoverflow.com/"}
)

然后:

// moduleX/views.go (or some other file in package moduleX)

package moduleX

func GetUrls() []string {
    return urls
}

然后:

// start.go

package main

import (
    "fmt"
    "myapp/moduleX"
)

func main() {
    for _, url := range moduleX.GetUrls() {
        fmt.Println(url)
    }
}

或者,更简单一点,只需从moduleX包中导出变量,为其提供大写名称。

例如:

// moduleX/urls.go

package moduleX

var URLs = []string{"http://google.com/", "http://stackoverflow.com/"}

然后:

// start.go

package main    

import (
    "fmt"
    "myapp/moduleX"
)

func main() {
    for _, url := range moduleX.URLs {
        fmt.Println(url)
    }
}

看看any of the Go source to see how they handle the same problem。一个很好的例子是the SHA512 source,其中冗长的变量存储在sha512block.go中,逻辑位于sha512.go