从Javaer变成gopher之指针

108 阅读2分钟

作为一个Java开发者,就是因为讨厌指针才选择了Java。但是go的指针却不同于c/c++中的指针这么灵活多变。

指针的定义


func main() {
   var ptrInt *int
   var ptrFloat32 *float32
   var ptrFloat64 *float64
   var ptrIBool *bool
   var ptrString *string
   fmt.Println(ptrInt)
   fmt.Println(ptrFloat32)
   fmt.Println(ptrFloat64)
   fmt.Println(ptrIBool)
   fmt.Println(ptrString)
}

每个基础类型都有自己的指针类型,当定义一个指针但是没有初始化时,他的默认值是nil

image.png

指针赋值

每个类型指针只能用对应的类型进行赋值,比如 *int只能赋值int类型的值。

func main() {
   var ptrInt *int
   var i = 10
   // 赋值
   ptrInt = &i
   fmt.Println(*ptrInt)
   // 改变值
   *ptrInt = 20
   fmt.Println(*ptrInt)
}

当然学过c/c++的大佬是心知肚明的,我这里就我个人的理解做一下解释。

image.png 在一块内存空间中,我们通过var i int 可以申请一块空间专门用来存储这个这个变量的值,如果在初始化时将i的值赋值为10,那么这个空间内的值就是10,但是不同的是在我们通过var ptr *int来定义一个指针时,他是不会申请一个内存空间的,如上边我们在打印各类型指针时,可以看到初始值都是nil。只有当我们给一个指针赋值的时候他才会去申请一个内存空间用来存放内容。这是因为指针在go中不基础类型变量,他没有自己的默认值。

另外指针和基础数据类型不同的是,指针存储的内容不是某个具体的值,而是一个地址,所以不能使用ptr = 10这种方式来进行初始化。只能通过取地址符&来进行赋值ptr = &i


func main() {
   var ptrInt *int
   var i = 10
   ptrInt = &i
   fmt.Println(ptrInt)
   // * 和 & 的作用正好相反,我们通过 & 取地址,通过 * 可以取指针变量指向的值
   fmt.Println(*ptrInt)

}

我们打印ptrInt*ptrInt

image.png

如果要修改指针的值除了重新赋予一个地址之外,我们也可以直接修改指针指向的那个值,但是这样也会导致指针指向的那个变量的值发生改变。


func main() {
    var i = 10
    ptrInt = &i
    fmt.Println("i的值", *ptrInt)
    fmt.Println("*ptrInt的值", *ptrInt)
    fmt.Println("ptrInt的值", ptrInt)
    *ptrInt = 20
    fmt.Println("i的值", *ptrInt)
    fmt.Println("*ptrInt的值", *ptrInt)
    fmt.Println("ptrInt的值", ptrInt)
}

image.png