使用gorilla/mux如何将URL拆分为多个文件?

huangapple go评论102阅读模式
英文:

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(&quot;/static/&quot;, http.StripPrefix(&quot;/static/&quot;, http.FileServer(http.Dir(&quot;./templates/static/&quot;))))
    // set up all the registered routes
    for _, rt = range(routes){
        r.HandleFunc(rt.path,rt.handler).Methods(rt.Method)
    }
    // and there&#39;s usually some other stuff that needs to go in here
    
    //before we finally serve the content here!
    http.ListenAndServe(&quot;:8080&quot;, nil)
}

yourmodule.go:

func init(){
    r = route{
        method=&quot;GET&quot;,
        path=&quot;/yourmodule/path/whatever&quot;,
        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)
}

Playground

英文:

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 (
	&quot;fmt&quot;
	&quot;github.com/gorilla/mux&quot;
	&quot;net/http&quot;
)

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, &quot;POST Handler&quot;)
}

func someHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, &quot;Normal Handler&quot;)
}

func main() {
	//define some handlers
	handlers := []handler{{path: &quot;/&quot;, f: somePostHandler, methods: []string{&quot;POST&quot;}}, {path: &quot;/&quot;, f: someHandler}}
	r := mux.NewRouter()
	http.Handle(&quot;/static/&quot;, http.StripPrefix(&quot;/static/&quot;, http.FileServer(http.Dir(&quot;./templates/static/&quot;))))
	// Initialise the handlers
	makeHandlers(handlers, r)
	http.Handle(&quot;/&quot;, r)
	http.ListenAndServe(&quot;:8080&quot;, nil)
}

Playground

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{&quot;http://google.com/&quot;, &quot;http://stackoverflow.com/&quot;}
)

Then:

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

package moduleX

func GetUrls() []string {
    return urls
}

Then:

// start.go

package main

import (
    &quot;fmt&quot;
    &quot;myapp/moduleX&quot;
)

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{&quot;http://google.com/&quot;, &quot;http://stackoverflow.com/&quot;}

and then:

// start.go

package main    

import (
    &quot;fmt&quot;
    &quot;myapp/moduleX&quot;
)

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.

huangapple
  • 本文由 发表于 2013年10月14日 16:53:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/19356619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定