Gorilla mux在子文件夹中的单独文件中定义路由吗?

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

Gorilla mux routes in separate files in subfolder?

问题

我正在尝试构建一个非常简单的Go Web应用程序,但是Go语言的“每个包一个文件夹”的结构对我来说很困难。

我正在使用github.com/gorilla/mux作为路由器,github.com/unrolled/render用于模板渲染。这意味着当应用程序启动时,我需要创建一个新的路由器和一个新的渲染器,并且我需要让所有的路由都能访问到渲染器。

在单个文件中,这非常容易实现:

func main() {
  
  ...

  r := render.New(render.Options{
    // 很多特定于应用程序的设置
  })

  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    r.HTML(w, http.StatusOK, "myTemplate", nil)
  })

  ...
}

然而,这就是我不理解Go的地方。因为我希望将路由放在一个子文件夹的单独文件中(我的项目会不断增长),这就要求它们必须在一个名为routes的包中。当然,这会导致渲染器变量无法访问。我不能只是在routes包中创建渲染器,因为render.New()调用依赖于我传入大量特定于应用程序的内容,比如模板文件夹和辅助函数的资源路径。

我尝试让我的处理函数在一个已初始化渲染器的结构体上工作...

func (app *App) Hello2(w http.ResponseWriter, r *http.Request) {
  app.Renderer.HTML(w, http.StatusOK, "myTemplate", nil)
}

但是我仍然困惑于如何在routes包中访问这个app *App,因为它是在main函数中初始化的。在Go中,如果你有一个扁平的文件列表,一切都变得非常容易,但是一旦你想要一点文件夹结构,包的设置就变得有问题了。

我可能漏掉了一些东西,所以任何帮助都将不胜感激。

英文:

I'm trying to build a very simple Go web application, and the golang "a folder per package" structure is making things difficult for me.

I'm using github.com/gorilla/mux as the router and github.com/unrolled/render for template rendering. This means that I need to create a new router and a new renderer when the app launches, and I need all my routes to access the renderer.

This is super easy to do in a single file:

func main() {
  
  ...

  r := render.New(render.Options{
    // a lot of app specific setup
  })


  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    r.HTML(w, http.StatusOK, "myTemplate", nil)
  })

  ...

}

However, this is where I don't understand Go. Because I want the routes in separate files in a subfolder (my project will grow), that forces them to be in a routes package. Of course that makes the renderer variable inaccesssible. I can't just create the renderer in the routes package, because the render.New() call relies on a me passing in a ton of app specific stuff like the template folder, and helpers for asset paths.

I went down the route of making my handler functions work on a struct with an already initialized renderer...

func (app *App) Hello2(w http.ResponseWriter, r *http.Request) {
  app.Renderer.HTML(w, http.StatusOK, "myTemplate", nil)
}

But I'm still confused as to how I'm going to access this app *App in the routes package when it's initialized in main. Everything in Go seems super easy if you have a flat list of files, but as soon as you want a bit of folder structure, the package setup becomes problematic.

There's probably something I'm missing here, so any help is appreciated.

答案1

得分: 0

这是关于在Go中处理依赖关系的一般信息。一个关键的技巧是,在你的视图可以导入的包中声明Render变量。你可以创建一个myapp/render包,其中包含一个在包本身中初始化(func init())或从main设置的var Render

但是你找到的上下文的东西听起来非常合理,尽管可能超出了这个应用程序的需求。它的好处是,因为上下文是在每个请求的代码中设置的,所以以后你可以扩展它来做一些巧妙的事情,比如使用Host:头来为通过不同域加载应用程序的人提供不同的Layout。如果Layout是内置的全局变量,你就无法做到这一点。这是一个真正的优势——我曾经试图将每个请求的更改添加到各种全局变量中的大型代码库中,这是一件很麻烦的事情。

英文:

Here's general info on dealing with dependencies in Go. A key trick is, you just have to declare the Render variable in a package that your views can import. You could create a myapp/render package with a var Render that's either inited in the package itself (func init()) or set from main.

But the context thing you found sounds totally sane, though it might be more than this app needs. The neat thing about it is that because the context is set in per-request code, later you could extend it to do sneaky things like use the Host: header to provide a different Layout for people loading the app via different domains. If the Layout is baked into a global, you can't. This can be a real advantage--I've tried to retrofit per-request changes onto big codebases whose config was sprayed around various global variables, and it's a pain.

huangapple
  • 本文由 发表于 2014年11月14日 11:05:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/26922236.html
匿名

发表评论

匿名网友

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

确定