我正在努力理解指针的概念。
我有三个包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)
}