¿Cómo usar var global a través de archivos en un paquete?

Tengo la siguiente estructura de archivos:

modelos / db.go

type DB struct { *sql.DB } var db *DB func init() { dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", DB_USER, DB_PASSWORD, DB_NAME) db, err := NewDB(dbinfo) checkErr(err) rows, err := db.Query("SELECT * FROM profile") checkErr(err) fmt.Println(rows) } func NewDB(dataSourceName string) (*DB, error) { db, err := sql.Open("postgres", dataSourceName) if err != nil { return nil, err } if err = db.Ping(); err != nil { return nil, err } return &DB{db}, nil } 

modelos / db_util.go

 func (p *Profile) InsertProfile() { if db != nil { _, err := db.Exec(...) checkErr(err) } else { fmt.Println("DB object is NULL") } } 

Cuando bash acceder a db en la función InsertProfile , dice NULL ptr exception . ¿Cómo db_utils.go a la base de db_utils.go en db_utils.go ?

No me gustaría capitalizar db (ya que daría acceso a todos los paquetes).

Obtengo la consulta devuelta desde el db en init() correctamente.

Editar: El problema es que usaste la statement de variable corta := y acabas de almacenar el valor de *DB creado en una variable local y no en la global.

Esta línea:

 db, err := NewDB(dbinfo) 

Crea 2 variables locales: db y err , y este db local no tiene nada que ver con su variable db global. Su variable global permanecerá nil . Debe asignar el *DB creado a la variable global. No use declaraciones de variables cortas pero asignaciones simples, por ejemplo:

 var err error db, err = NewDB(dbinfo) if err != nil { log.Fatal(err) } 

La respuesta original sigue.


Es un tipo de puntero, debe inicializarlo antes de usarlo. El valor cero para los tipos de puntero es nil .

No tiene que exportarlo (eso es lo que hace comenzar con una letra mayúscula). Tenga en cuenta que no importa que tenga varios archivos, siempre que sean parte del mismo paquete, pueden acceder a los identificadores definidos entre sí.

Una buena solución sería hacerlo en la función package init() que se llama automáticamente.

Tenga en cuenta que sql.Open() solo puede validar sus argumentos sin crear una conexión a la base de datos. Para verificar que el nombre de la fuente de datos sea válido, llame a DB.Ping() .

Por ejemplo:

 var db *sql.DB func init() { var err error db, err = sql.Open("yourdrivername", "somesource") if err != nil { log.Fatal(err) } if err = db.Ping(); err != nil { log.Fatal(err) } } 

icza ya ha respondido correctamente a su problema específico, pero vale la pena agregar alguna explicación adicional sobre lo que está haciendo mal para que comprenda cómo no cometer el error en el futuro. En Go, la syntax := para la asignación crea nuevas variables con los nombres a la izquierda de := , posiblemente paquete de sombreado, o incluso variables de función / método de ámbito principal. Como ejemplo:

 package main import "fmt" var foo string = "global" func main() { fmt.Println(foo) // prints "global" // using := creates a new function scope variable // named foo that shadows the package scope foo foo := "function scope" fmt.Println(foo) // prints "function scope" printGlobalFoo() // prints "global" if true { foo := "nested scope" fmt.Println(foo) // prints "nested scope" printGlobalFoo() // prints "global" } // the foo created inside the if goes out of scope when // the code block is exited fmt.Println(foo) // prints "function scope" printGlobalFoo() // prints "global" if true { foo = "nested scope" // note just = not := } fmt.Println(foo) // prints "nested scope" printGlobalFoo() // prints "global" setGlobalFoo() printGlobalFoo() // prints "new value" } func printGlobalFoo() { fmt.Println(foo) } func setGlobalFoo() { foo = "new value" // note just = not := } 

Nota Go no tiene manera de eliminar o deshacer una variable, por lo que una vez que ha sombreado variables de ámbito más alto (como crear una variable de ámbito de función con el mismo nombre que una variable de ámbito de paquete), no hay forma de acceder al scope superior variable dentro de ese bloque de código.

También tenga en cuenta que := es una abreviatura de var foo = . Ambos actúan exactamente de la misma manera, sin embargo := es solo una syntax válida dentro de una función o método, mientras que la syntax var es válida en todas partes.