为了账号安全,请及时绑定邮箱和手机立即绑定

全局空间中的 Nil 指针异常

全局空间中的 Nil 指针异常

Go
慕斯王 2022-09-12 20:34:47
我试图理解指针的概念。我有三个软件包主,型号和控制器在我的模型中.gotype Database struct {    config  string    port    int}var DB *Databasefunc GetDatabase() *Database {    fmt.Println("Reporting from Models.")    DB = &Database{config: "This is stunning!", port: 3306}    fmt.Printf("%v, %T\n", DB, DB)    return DB}在控制器中。govar DB *models.Database = models.DBfunc GetController() {    fmt.Println("Reporting from Controllers!")    fmt.Printf("%v, %T\n", DB, DB)}在主.govar DB *models.Databasefunc 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.DatabaseReporting from Controllers!<nil>, *models.DatabaseREporting from main&{This is stunning! 3306}, *models.Database我在这里的问题是,为什么我要进入数据库的控制器?我的直觉是,它在模型内的包级别访问全局DB变量,这是自它未启动以来。但是,由于它是一个引用,并且我试图在我的GetDatabase函数中为它提供适当的引用,为什么当我尝试访问控制器中的该变量时,这种更改没有得到反映?nilnil
查看完整描述

2 回答

?
元芳怎么了

TA贡献1798条经验 获得超7个赞

指针本质上是整数,其中它们存储的数字是内存中其他变量的地址。如果您不习惯指针,但来自具有数组的语言,则将指针视为保存数组索引的整数(其中数组是内存)或多或少是正确的。


当你运行这样的语句时,这个....


package controllers


var DB *models.Database = models.DB

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


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


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


如果你这样做了...


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

controllers.DB = models.DB // non-nil address is copied

然后两个变量将包含相同的地址,并且对它们现在都指向的单个变量的更改将通过两个指针可见。但是,重新分配变量本身(即 )不会影响其他变量。Databasemodels.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"


查看完整回答
反对 回复 2022-09-12
?
当年话下

TA贡献1890条经验 获得超9个赞

如果你想分享一些东西,你需要一个指针,但不是一个指针,一个实际分配的指针。然后,您还需要使用取消引用来更新共享指针的每个实例,基本上取消引用是更新存储在指针指向的地址的数据的方式。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, %T\n", 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)

}


查看完整回答
反对 回复 2022-09-12
  • 2 回答
  • 0 关注
  • 76 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号