2015-05-19 3 views
0

У меня есть два .go файлов: a.go и b.gogolang, дБ * sql.DB объявлен в a.go не доступен в b.go

Я объявляющий в глобальном дб * sql.DB для моего подключения к базе данных mysql.

Моя цель - объявить db один раз и использовать его во всех моих файлах пакета, в данном случае b.go.

Все строит хорошо, но я получаю сообщение об ошибке при ударе мои API конечных точек/пользователей

22:48:52 app   | 2015/05/18 22:48:52 http: panic serving 127.0.0.1:55742: runtime error: invalid memory address or nil pointer dereference 
goroutine 6 [running]: 
net/http.func·011() 
    /usr/local/go/src/net/http/server.go:1130 +0xbb 
database/sql.(*DB).conn(0x0, 0x4da104, 0x0, 0x0) 
    /usr/local/go/src/database/sql/sql.go:634 +0x7ae 
database/sql.(*DB).query(0x0, 0x809e70, 0x16, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0) 
    /usr/local/go/src/database/sql/sql.go:933 +0x43 
database/sql.(*DB).Query(0x0, 0x809e70, 0x16, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) 
    /usr/local/go/src/database/sql/sql.go:924 +0xa6 
main.GetUsers(0x0, 0x0, 0x0) 
    /var/www/zazok.com/api/src/app/user.go:15 +0xc0 
main.func·001(0xc2080424d0) 
    /var/www/zazok.com/api/src/app/app.go:35 +0x1f 
github.com/gin-gonic/gin.(*Context).Next(0xc2080424d0) 
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/context.go:114 +0x95 
github.com/gin-gonic/gin.func·006(0xc2080424d0) 
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/logger.go:49 +0x68 
github.com/gin-gonic/gin.(*Context).Next(0xc2080424d0) 
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/context.go:114 +0x95 
github.com/gin-gonic/gin.func·009(0x7f1123351408, 0xc208036280, 0xc2080328f0, 0x0, 0x0, 0x0) 
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/routergroup.go:57 +0xa3 
github.com/julienschmidt/httprouter.(*Router).ServeHTTP(0xc20803af60, 0x7f1123351408, 0xc208036280, 0xc2080328f0) 
    /var/www/zazok.com/api/src/github.com/julienschmidt/httprouter/router.go:299 +0x18e 
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc208042000, 0x7f1123351408, 0xc208036280, 0xc2080328f0) 
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/gin.go:156 +0x4d 
net/http.serverHandler.ServeHTTP(0xc208030120, 0x7f1123351408, 0xc208036280, 0xc2080328f0) 
    /usr/local/go/src/net/http/server.go:1703 +0x19a 
net/http.(*conn).serve(0xc2080361e0) 
    /usr/local/go/src/net/http/server.go:1204 +0xb57 
created by net/http.(*Server).Serve 
    /usr/local/go/src/net/http/server.go:1751 +0x35e 

a.go

package main 

import (
    "database/sql" 
    "github.com/gin-gonic/gin" 
    _ "github.com/go-sql-driver/mysql" 
) 

var (
    prefix string = "/api/v1" // API prefix 
    db  *sql.DB 
) 

// Boots up this whole thing 
func main() { 
    // Setting up DB 
    db, err := sql.Open("mysql", "root:[email protected](/var/run/mysqld/mysqld.sock)/test.com?collation=utf8_general_ci") 
    if err != nil { 
     panic(err) 
    } 

    defer db.Close() 

    err = db.Ping() 
    if err != nil { 
     panic(err) 
    } 

    r := gin.New() 

    r.Use(gin.Logger()) 

    r.GET(prefix+"/users", func(c *gin.Context) { 

     t := GetUsers() 

     c.JSON(200, t) 
    }) 

    r.Run(":3000") 
} 

b.go

package main 

import (
    "log" 
) 

type User struct { 
    Id   int `json:"id"` 
    Name  string `json:"name"` 
} 

func GetUsers() []User { 
    a := []User{} 

    _, err := db.Query("SELECT name FROM users") 
    if err != nil { 
     log.Fatal(err) 
    } 

    return a 
} 
+0

возможно дубликат [Go глобальной переменной и краткое определение переменной] (http://stackoverflow.com/questions/28284138/go-global-variable-and-short -variable-definition) –

ответ

1

EDIT : Как указал DaveC, проблема в том, что u sing := инициирует переменную только в локальной области. Декларирование эээ заранее заставит sql.Open, чтобы сохранить связь в глобальном, а не создавать новый локальный, следующим образом:

func main() { 
    var err error // <- Declare err 

    // Use = instead of := 
    db, err = sql.Open("mysql", "root:[email protected](/var/run/mysqld/mysqld.sock)/test.com?collation=utf8_general_ci") 
    ... 

Это изменение под влиянием DaveC, Tomasz, и Бен Дарнелл (ответ Бен Дарнелла: Go global variable and short variable definition)

/EDIT

Лично я предпочитаю, чтобы избежать глобалам, где это возможно. Чтобы сделать это, измените GetUsers на аргумент * sql.DB. Затем измените свой a.go на пользовательский gin.HandlerFunc, который является приемником базы данных. В примере я создал структуру инструментов, которую вы могли бы использовать для передачи многих «глобальных» вещей.

package main 

import (
    "database/sql" 

    "github.com/gin-gonic/gin" 
    _ "github.com/go-sql-driver/mysql" 
) 

var (
    prefix = "/api/v1" // API prefix 
) 

type tools struct { 
    db *sql.DB 
} 

func (t tools) dispatch() gin.HandlerFunc { 
    return func(c *gin.Context) { 
     GetUsers(t.db) 
    } 
} 

// Boots up this whole thing 
func main() { 
    // Setting up DB 
    db, err := sql.Open("mysql", "root:[email protected](/var/run/mysqld/mysqld.sock)/test.com?collation=utf8_general_ci") 

    if err != nil { 
     panic("DB connection failed") 
    } 
    defer db.Close() 

    t := tools{db} 

    r := gin.New() 

    r.Use(gin.Logger()) 

    r.GET(prefix+"/users", t.dispatch()) 

    r.Run(":3000") 
} 
+0

Спасибо! Это прекрасно работает – Andrey

+0

и полностью игнорирует основную причину ... –

+0

@DaveC вы можете уточнить? Мне лично выгодно использовать структуру для передачи необходимых мне данных, а не объявление глобальных переменных. Также очень удобно создавать пользовательскую функцию-обработчик для http-материала. Что не так с моим ответом? – vastlysuperiorman

3

Я думаю, что это классическая ошибка Go, и она не имеет ничего общего с использованием нескольких файлов.

Это заявление:

db, err := sql.Open("mysql", ...) 

объявляет новую переменную db в основной объем (обратите внимание :=) и ваша глобальная переменная нетронутым (ноль).

Вы можете легко исправить:

var err error 
db, err = sql.Open("mysql", ...) 

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

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