我有以下文件结构:
模型/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")
}
}
当我尝试在 InsertProfile
函数中访问 db
时,它显示 NULL ptr exception
。如何访问 db_utils.go
中的 db
?
我不想将 db
大写(因为它会提供对所有包的访问权限)。
我在 init()
中正确地获取了从 db
返回的 QUERY。
最佳答案
编辑:问题是您使用了Short variable declaration :=
你刚刚存储了创建的 *DB
局部变量中的值而不是全局变量中的值。
这一行:
db, err := NewDB(dbinfo)
创建 2 个局部变量:db
和 err
, 而这个本地 db
与你的全局db
无关多变的。您的全局变量将保持 nil
.您必须分配创建的 *DB
到全局变量。不要使用简短的变量声明,而是简单的 assignment ,例如:
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)
}
}
关于pointers - 如何跨包中的文件使用全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41993188/