質問

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.

役に立ちましたか?

解決 2

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

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{"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.

他のヒント

Why not get the handlers to insert themselves into the routes table?

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

So something like:


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
}

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.

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top