当前位置:  开发笔记 > 编程语言 > 正文

如何在包中的文件中使用全局var?

如何解决《如何在包中的文件中使用全局var?》经验,为你挑选了2个好方法。

我有以下文件结构:

车型/ 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
}

车型/ db_util.go

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

当我尝试访问dbInsertProfile功能,它说NULL ptr exception.如何访问dbdb_utils.go

我不想大写db(因为它可以访问所有包).

我正在从返回的查询dbinit()正确.



1> icza..:

编辑:问题是您使用了短变量声明, :=并且您只是将创建的*DB值存储在局部变量中而不是全局变量中.

这一行:

db, err := NewDB(dbinfo)

创建2个局部变量:dberr,这个局部变量db与全局db变量无关.您的全局变量将保留nil.您必须将创建的内容分配给*DB全局变量.不要使用简短的变量声明,而是简单的赋值,例如:

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

原始答案如下.


它是一种指针类型,您必须在使用它之前对其进行初始化.指针类型的零值是nil.

你不必导出它(这是以大写字母开头的).请注意,只要它们是同一个包的一部分,您就拥有多个文件并不重要,它们可以访问彼此定义的标识符.

一个好的解决方案是在init()自动调用的包函数中执行此操作.

请注意,sql.Open()可能只是在不创建与数据库的连接的情况下验证其参数.要验证数据源名称是否有效,请调用DB.Ping().

例如:

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


@lionelmessi我的猜测是,您使用了短变量声明`:=`,而只是将创建的* DB值存储在本地变量中,而不是全局变量中。看不到您的消息来源就无法告诉您,因此请客气并张贴。

2> Endophage..:

icza已经正确回答了你的具体问题,但值得为你的错误添加一些额外的解释,以便你了解如何在未来犯错误.在Go中,:=赋值语法创建了新变量,其名称:=可能是阴影包的左侧,甚至是父范围函数/方法变量.举个例子:

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

注意Go无法删除或取消设置变量,因此一旦您隐藏了更高的范围变量(例如通过创建与包范围变量同名的函数范围变量),就无法访​​问更高的范围该代码块中的变量.

还要注意这:=是一个简写var foo =.两者的行为方式完全相同,但:=只是函数或方法中的有效语法,而var语法在任何地方都有效.

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有