全局空间中出现零指针异常



我正在努力理解指针的概念。

我有三个包main、型号和控制器

在我的型号中。go

type Database struct {
config  string
port    int
}
var DB *Database
func GetDatabase() *Database {
fmt.Println("Reporting from Models.")
DB = &Database{config: "This is stunning!", port: 3306}
fmt.Printf("%v, %Tn", DB, DB)
return DB
}

控制器中。转到

var DB *models.Database = models.DB
func GetController() {
fmt.Println("Reporting from Controllers!")
fmt.Printf("%v, %Tn", DB, DB)
}

main.go

var DB *models.Database
func main() {
DB = models.GetDatabase()
controllers.GetController()
fmt.Println("REporting from main")
fmt.Printf("%v, %Tn", DB, DB)
}

输出

Reporting from Models.
&{This is stunning! 3306}, *models.Database
Reporting from Controllers!
<nil>, *models.Database
REporting from main
&{This is stunning! 3306}, *models.Database

我的问题是,为什么我要在DB的控制器中获取nil?我的直觉是,它在模型内部的包级别访问全局DB变量,因为它没有启动,所以是nil。但是,既然它是一个引用,我正试图在GetDatabase函数中为它提供一个适当的引用,为什么当我试图访问控制器中的变量时,这种变化没有得到反映?

指针本质上是整数,它们存储的数字是内存中其他变量的地址。如果你不习惯指针,但来自一种有数组的语言,那么将指针视为包含数组索引的整数或多或少是正确的,其中数组是内存。

当你运行这样的语句时。。。。

package controllers
var DB *models.Database = models.DB

这里真正要做的是有效的整数赋值,其中models.DB的值按值复制到变量controllers.DB中。在执行这行代码的时间点上,models.DB的值为nil,因此将地址nil复制到controllers.DB中。

在按值复制之后,对models.DB变量的任何更改都将与controllers.DB变量完全解耦。它们是两个独立的东西,它们都指向nil。现在,当您将某个实际DB实例的地址分配给models.DB时,models.DB的值会更改,但不相关的变量controllers.DB不受影响。

对一个变量的更改(即赋值(不会反映到其他变量。但是,如果两个指针指向同一个内存,并且您更改了内存本身,那么通过两个指针可以看到这些更改。

如果你这样做。。。

models.DB = &Database{} // non-nil address
controllers.DB = models.DB // non-nil address is copied

那么两个变量都将包含相同的地址,并且对它们现在都指向的单个Database变量的更改将通过两个指针可见。但是,重新分配变量本身(即models.DB = nil(不会影响其他变量。

回到阵列示例,您已经有效地做到了这一点:

arr := []string{"zero", "one", "two", "three"}
idx1 := 0 // ie models.DB
idx2 := 0 // ie controllers.DB
idx1 = idx2 // copy 0 by value into idx1
idx2 = 1 // does not affect idx1, which is still 0
arr[idx1] // "zero"
arr[idx2] // "one"

如果你想共享一些东西,你需要一个指针,但不是nil指针,一个实际分配的指针。然后,您还需要使用去引用来更新共享指针的每个实例,基本上,去引用是指如何更新存储在指针指向的地址的数据。

var DB = &Database{}
func GetDatabase() *Database {
// an asterisk before an expression is how you dereference a pointer
*DB = Database{config: "This is stunning!", port: 3306}
}
var DB = models.DB
func GetController() {
fmt.Printf("%v, %Tn", DB, DB) // not nil anymore
}
var DB = models.DB
func main() {
// you can ommit the assignment since GetDatabase() updates the shared 
// pointer of models.DB
_ = models.GetDatabase()
fmt.Println(DB)
}

相关内容

  • 没有找到相关文章

最新更新