Маршруты мультиплексора Gorilla в отдельных файлах в подпапке?

Я пытаюсь создать очень простое веб-приложение Go, и структура golang «папка для каждого пакета» усложняет мне задачу.

Я использую github.com/gorilla/mux в качестве маршрутизатора и github.com/unrolled/render для рендеринга шаблонов. Это означает, что мне нужно создать новый маршрутизатор и новый рендерер при запуске приложения, и мне нужны все мои маршруты для доступа к рендереру.

Это очень легко сделать в одном файле:

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

  ...

}

Однако здесь я не понимаю Go. Поскольку я хочу, чтобы маршруты были в отдельных файлах в подпапке (мой проект будет расти), это заставляет их быть в пакете routes. Конечно, это делает переменную рендерера недоступной. Я не могу просто создать рендерер в пакете routes, потому что вызов render.New() полагается на то, что я передаю массу специфических вещей приложения, таких как папка шаблона и помощники для путей ресурсов.

Я пошел по пути того, чтобы заставить мои функции обработчика работать со структурой с уже инициализированным средством визуализации...

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

Но я все еще не понимаю, как мне получить доступ к этому app *App в пакете routes, когда он инициализируется в main. Все в Go кажется очень простым, если у вас есть плоский список файлов, но как только вам нужна небольшая структура папок, установка пакета становится проблематичной.

Вероятно, мне здесь чего-то не хватает, поэтому любая помощь приветствуется.


person Ronze    schedule 14.11.2014    source источник
comment
Погуглив, я нашел это решение: github.com/unrolled/render/issues/ 7#issuecomment-61735461. Кажется, это помогает, но является ли это эффективным решением? Кажется странным, что мне нужно прикреплять один и тот же объект к каждому отдельному вызову в обработчике промежуточного программного обеспечения.   -  person Ronze    schedule 14.11.2014
comment
Я думаю, что это разумный путь. Вы можете создать пакет myapp/render, который просто устанавливает var Render в своем init() (или даже просто объявляет переменную и позволяет main.main() установить ее). Но настройка, которую вы связали, предоставляет возможность позже изменить поведение, если, скажем, конфигурация Render когда-нибудь не будет одинаковой для всех запросов (например, вы размещаете версии своего приложения в двух доменах и используете разные Layout для каждого).   -  person twotwotwo    schedule 14.11.2014


Ответы (1)


Вот общая информация о работе с зависимостями в Go. Ключевой трюк заключается в том, что вам просто нужно объявить переменную Render в пакете, который ваши представления могут импортировать. Вы можете создать пакет myapp/render с var Render, который либо инициируется в самом пакете (func init()), либо устанавливается из main.

Но контекст, который вы нашли, звучит совершенно разумно, хотя это может быть больше, чем нужно этому приложению. Преимущество этого заключается в том, что, поскольку контекст устанавливается в коде для каждого запроса, позже вы можете расширить его, чтобы делать хитрые вещи, такие как использование заголовка Host:, чтобы предоставить другой Layout для людей, загружающих приложение через разные домены. Если Layout запечется в глобальном, вы не сможете. Это может быть реальным преимуществом — я пытался модифицировать изменения для каждого запроса в больших кодовых базах, конфигурация которых была распылена вокруг различных глобальных переменных, и это было мучительно.

person twotwotwo    schedule 14.11.2014
comment
Ах, это имеет массу смысла. Огромное спасибо. Все еще ищу свой путь вокруг Go. - person Ronze; 14.11.2014