2015-11-11 6 views
5

На данный момент я пытаюсь создать небольшой веб-проект, используя Go для обработки данных на сервере.Перейти с помощью мультиплексора Router - Как передать мою БД моим обработчикам

Я пытаюсь передать мое соединение с базой данных для моего HandlerFunc (но), но он не работает должным образом. Я довольно новичок в голанге, поэтому, возможно, я не понял некоторых основных принципов этого языка.

Мой главный FUNC выглядит следующим образом:

func main() { 

    db, err := config.NewDB("username:[email protected]/databasename?charset=utf8&parseTime=True") 
    if err != nil { 
     log.Panic(err) 
    } 
    env := &config.Env{DB: db} 

    router := NewRouter(env) 
    log.Fatal(http.ListenAndServe(":8080", router)) 
} 

Мой маршрутизатор:

func NewRouter(env *config.Env) *mux.Router { 
    router := mux.NewRouter().StrictSlash(true) 
    for _, route := range routes { 
     var handler http.Handler 

     handler = route.HandlerFunc 
     handler = Logger(handler, route.Name) 

     router. 
      Methods(route.Method). 
      Path(route.Pattern). 
      Name(route.Name). 
      Handler(handler) 
    } 
    return router 
} 

и мои маршруты:

type Route struct { 
    Name  string 
    Method  string 
    Pattern  string 
    HandlerFunc http.HandlerFunc 
} 

type Routes []Route 

var routes = Routes{ 
    Route{ 
     "Index", 
     "GET", 
     "/", 
     controller.Index, 
    }, 
    Route{ 
     "Show", 
     "GET", 
     "/todos/{todoId}", 
     controller.TodoShow, 
    }, 
    Route{ 
     "Create", 
     "POST", 
     "/todos", 
     controller.TodoCreate, 
    }, 
} 

Так что - как я могу передать свою "окр" (или env.DB) моим FuncHandlers? Я много пробовал, но никто из них не работал.

ответ

11

У вас есть три варианта:

  1. сделать ваше подключение к базе данных пула глобальной , так что вам не нужно его передавать. sql.DB безопасен для одновременного доступа, и это самый простой подход. Недостатком является то, что он делает тестирование сложнее и запутывает «где» собирается пул - например,

    var db *sql.DB 
    
    func main() { 
        var err error 
        db, err = sql.Open(...) 
        // Now accessible globally, no need to pass it around 
        // ... 
    } 
    
  2. Wrap обработчики в затворе, что делает его доступным для внутреннего обработчика. Вы должны будете адаптировать это к вашим диапазонам более трассам подход, который немного тупые ИМО, и делает его труднее увидеть, что существуют маршруты, но я отвлекся, например:

    func SomeHandler(db *sql.DB) http.HandlerFunc { 
        fn := func(w http.ResponseWriter, r *http.Request) { 
         res, err := db.GetThings() 
         // etc. 
        } 
    
        return http.HandlerFunc(fn) 
    } 
    
    func main() { 
        db, err := sql.Open(...) 
        http.HandleFunc("/some-route", SomeHandler(db)) 
        // etc. 
    } 
    
  3. Создать тип пользовательского обработчика, который принимает обработчик - например,

    type AppHandler struct { 
        Handler func(env *config.Env, w http.ResponseWriter, r *http.Request) 
        Env *config.Env 
    
    // ServeHTTP allows your type to satisfy the http.Handler interface. 
    func (ah *AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 
        ah.Handler(ah.Env, w, r) 
    } 
    
    func SomeHandler(env *config.Env, w http.ResponseWriter, r *http.Request) { 
        res, err := env.DB.GetThings() 
        // etc. 
    } 
    

Обратите внимание, что (бесстыжие плагин!) Я written about the last approach in detail, и Алекс Эдвардс имеет excellent blog post на подходах к доступа к БД пулы в программах Go, а также.

Единственный строгий совет, который я могу дать, заключается в том, что вы должны уклоняться от передачи вашего пула БД вокруг в контексте запроса, что является неэффективным и не является хорошей практикой (контексты запросов относятся к временным объектам с запросом).

+1

Большое спасибо, Я уже посмотрел блог-блог Alex Edwards и попытался реализовать его решение закрытия (используя свой пример в https: //gist.github.com/alexedwards/5cd712192b4831058b21) Теперь я изменил его и использовал глобальный var в моем пакете моделей, и он работает. Я все еще не уверен, что это лучшее решение для моего проекта, но на данный момент это будет соответствовать моим потребностям. – Newbie

0

Вы всегда можете указать «env» как global variable.

Но прежде чем все будут ненавидеть меня, это нехорошее решение! Вы должны создать пакет, который инкапсулирует доступ к вашей базе данных с помощью публичных функций, которые указывают ваше точное намерение.

Что-то вдоль линий

Package db 

var config .... 

func ShowTodos(params ...) result { 
    your database access code here.... 
} 

и вашего доступа функции маршрутизатора, он с

db.ShowTodos(...) 

 Смежные вопросы

  • Нет связанных вопросов^_^