全局空间中的 Nil 指针异常

我试图理解指针的概念。


我有三个软件包主,型号和控制器


在我的模型中.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, %T\n", DB, DB)

    return DB

}

在控制器中。go


var DB *models.Database = models.DB


func GetController() {

    fmt.Println("Reporting from Controllers!")

    fmt.Printf("%v, %T\n", DB, DB)

}

在主.go


var DB *models.Database


func main() {

    DB = models.GetDatabase()

    controllers.GetController()

    fmt.Println("REporting from main")

    fmt.Printf("%v, %T\n", 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变量,这是自它未启动以来。但是,由于它是一个引用,并且我试图在我的GetDatabase函数中为它提供适当的引用,为什么当我尝试访问控制器中的该变量时,这种更改没有得到反映?nilnil


慕斯王
浏览 77回答 2
2回答

元芳怎么了

指针本质上是整数,其中它们存储的数字是内存中其他变量的地址。如果您不习惯指针,但来自具有数组的语言,则将指针视为保存数组索引的整数(其中数组是内存)或多或少是正确的。当你运行这样的语句时,这个....package controllersvar DB *models.Database = models.DB您在这里真正要做的实际上是整数赋值,其中 的值按值复制到变量中。在执行此行代码的时间点,值为 ,因此将地址复制到 中。models.DBcontrollers.DBmodels.DBnilnilcontrollers.DB在此按值复制之后,对变量的任何更改都将与变量完全分离。它们是两个独立的东西,它们都指向.现在,当您将某个实际实例的地址分配给 时,值会发生变化,但不相关的变量不受影响。models.DBcontrollers.DBnilDBmodels.DBmodels.DBcontrollers.DB对一个变量的更改(即赋值)不会镜像到其他变量。但是,如果两个指针指向同一内存,并且您更改了内存本身,则通过两个指针都可以看到这些更改。如果你这样做了...models.DB = &Database{} // non-nil addresscontrollers.DB = models.DB // non-nil address is copied然后两个变量将包含相同的地址,并且对它们现在都指向的单个变量的更改将通过两个指针可见。但是,重新分配变量本身(即 )不会影响其他变量。Databasemodels.DB = nil回到数组示例,您已经有效地完成了此操作:arr := []string{"zero", "one", "two", "three"}idx1 := 0 // ie models.DBidx2 := 0 // ie controllers.DBidx1 = idx2 // copy 0 by value into idx1idx2 = 1 // does not affect idx1, which is still 0arr[idx1] // "zero"arr[idx2] // "one"

当年话下

如果你想分享一些东西,你需要一个指针,但不是一个指针,一个实际分配的指针。然后,您还需要使用取消引用来更新共享指针的每个实例,基本上取消引用是更新存储在指针指向的地址的数据的方式。nilvar DB = &Database{}func GetDatabase() *Database {&nbsp; &nbsp; // an asterisk before an expression is how you dereference a pointer&nbsp; &nbsp; *DB = Database{config: "This is stunning!", port: 3306}}var DB = models.DBfunc GetController() {&nbsp; &nbsp; fmt.Printf("%v, %T\n", DB, DB) // not nil anymore}var DB = models.DBfunc main() {&nbsp; &nbsp; // you can ommit the assignment since GetDatabase() updates the shared&nbsp;&nbsp; &nbsp; // pointer of models.DB&nbsp; &nbsp; _ = models.GetDatabase()&nbsp; &nbsp; fmt.Println(DB)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go