pointers - plusieurs - variable globale c++




Comment utiliser la var globale entre les fichiers d'un paquet? (2)

J'ai la structure de fichier suivante:

modèles / 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
}

models / db_util.go

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

Lorsque j'essaie d'accéder à la db de InsertProfile dans la fonction InsertProfile , elle indique une NULL ptr exception . Comment accéder à la db de db_utils.go dans db_utils.go ?

Je ne voudrais pas capitaliser sur la db (car cela donnerait accès à tous les paquets).

Je reçois correctement la requête QUERY de la db de données init() .


icza a déjà correctement répondu à votre problème spécifique, mais il est utile d’ajouter quelques explications sur ce que vous faites de travers pour que vous compreniez bien comment ne pas commettre l’erreur à l’avenir. Dans Go, la syntaxe := for assign crée de nouvelles variables avec les noms situés à gauche de := , éventuellement un package d'observation, ou même des variables de fonction / méthode de portée. Par exemple:

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 :=
}

Remarque Go n'a aucun moyen de supprimer ou de supprimer une variable. Par conséquent, une fois que vous avez observé une variable de portée supérieure (par exemple, en créant une variable de portée de fonction du même nom qu'une variable de portée de package), vous ne pouvez plus accéder à la portée supérieure. variable dans ce bloc de code.

Sachez également que := est un raccourci pour var foo = . Les deux fonctionnent exactement de la même manière, cependant := n’est que la syntaxe valide dans une fonction ou une méthode, tandis que la syntaxe var est valide partout.


Edit: Le problème est que vous avez utilisé Short variable declaration := et que vous venez de stocker la valeur *DB créée dans une variable locale et non dans la variable globale.

Cette ligne:

db, err := NewDB(dbinfo)

Crée 2 variables locales: db et err , et cette db locale n'a rien à voir avec votre variable de db globale. Votre variable globale restera nil . Vous devez affecter le *DB créé à la variable globale. N'utilisez pas de déclaration de variable courte, mais une assignment simple, par exemple:

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

La réponse originale suit.

C'est un type de pointeur, vous devez l'initialiser avant de l'utiliser. La valeur zéro pour les types de pointeur est nil .

Vous n’avez pas à l’exporter (c’est ce qui commence par une majuscule). Notez que vous avez plusieurs fichiers dans la mesure où ils font partie du même package, ils peuvent accéder aux identifiants définis les uns dans les autres.

Une bonne solution serait de le faire dans la fonction package init() qui est appelée automatiquement.

Notez que sql.Open() peut simplement valider ses arguments sans créer de connexion à la base de données. Pour vérifier que le nom de la source de données est valide, appelez DB.Ping() .

Par exemple:

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




nullreferenceexception