乐趣区

关于golang:Go-语言什么情况下应该使用指针

什么是指针

咱们都晓得,程序运行时的数据是寄存在内存中的,每一个存储在内存中的数据都有一个编号,这个编号就是内存地址。咱们能够依据这个内存地址来找到内存中存储的数据,而内存地址能够被赋值给一个指针。咱们也能够简略的了解为指针就是内存地址。

指针的申明和定义

在 Go 语言中,获取一个指针,间接应用取地址符 & 就能够。
示例:

func main() {
  name := "微客鸟窝"
  nameP := &name // 取地址
  fmt.Println("name 变量值为:", name)
  fmt.Println("name 变量的内存地址为:", nameP)
}
// 运行后果://name 变量值为:微客鸟窝
//name 变量的内存地址为:0xc00004e240
  • nameP 指针的类型是 *string
  • Go 语言中,* 类型名 示意一个对应的指针类型
变量 内存中数据 内存地址
name := “ 微客鸟窝 ” 微客鸟窝 0xc00004e240
nameP := &name 0xc00004e240 0xc00004e360

从下面表格能够看到:

  1. 一般变量 name 的值是微客鸟窝,寄存在内存地址为 0xc00004e240 的内存中
  2. 指针变量 namep 的值是一般变量的内存地址 0xc00004e240
  3. 指针变量 nameP 的值寄存在 内存地址为 0xc00004e360 的内存中
  4. 一般变量存的是数据,指针变量存的是数据的地址

var 关键字申明

咱们也能够应用 var 关键字申明

var nameP *string
nameP = &name

new 函数申明

nameP := new(string)
nameP = &name

能够传递类型给这个内置的 new 函数,它会返回对应的指针类型。

指针的操作

这里强调一下:
指针变量 是一个变量,这个变量的值是 指针 (内存地址)!
指针变量 是一个变量,这个变量的值是 指针 (内存地址)!
指针变量 是一个变量,这个变量的值是 指针(内存地址)!

  1. 获取指针指向的值:
    只须要在指针变量钱加 * 号即可取得指针变量值所对应的数据:

    nameV := *nameP
    fmt.Println("nameP 指针指向的值为:",nameV) //nameP 指针指向的值为: 微客鸟窝
  2. 批改指针指向的值:

    *nameP = "公众号: 微客鸟窝" // 批改指针指向的值
    fmt.Println("nameP 指针指向的值为:",*nameP)
    fmt.Println("name 变量的值为:",name)
    // 运行后果://nameP 指针指向的值为: 公众号: 微客鸟窝
    //name 变量的值为: 公众号: 微客鸟窝
  3. 咱们发现 nameP 指针指向的值被扭转了,变量 name 的值也被扭转了
  4. 因为变量 name 存储数据的内存就是指针 nameP 指向的内存,这块内存被 nameP 批改后,变量 name 的值也被批改了。
  5. 通过 var 关键字间接定义的指针变量是不能进行赋值操作的,因为它的值为 nil,也就是还没有指向的内存地址

    // 谬误示例
    var intP *int
    *intP = 10  // 谬误,应该先给调配一块内存,内存地址作为变量 intP 的值,这个内存就能够寄存 10 了。// 应该应用
    var intP *int  // 申明 int 类型的指针变量 intP
    intP = new(int) // 给指针调配一块内存
    *intP = 66 
    fmt.Println(":::",intP)  //::: 0xc0000ac088
    fmt.Println(*intP) //66
    // 简短写法
    var intP := new(int)
    *intP=66

指针参数

当给一个函数应用指针作为参数的时候,就能够在函数中,通过形参扭转实参的值:

func main() {
    name := "无尘"
    modify(&name)
    fmt.Println("name 的值为:",name)
}
func modify(name *string)  {*name = "wucs"}
// 运行后果://name 的值为: wucs

指针接收者

  1. 如果接收者类型是 map、slice、channel 这类援用类型,不应用指针;
  2. 如果须要批改接收者,那么须要应用指针;
  3. 如果接收者是比拟大的类型,能够思考应用指针,因为内存拷贝便宜,所以效率高。

什么状况下应用指针

  • 不要对 map、slice、channel 这类援用类型应用指针;
  • 如果须要批改办法接收者外部的数据或者状态时,须要应用指针;
  • 如果须要批改参数的值或者外部数据时,也须要应用指针类型的参数;
  • 如果是比拟大的构造体,每次参数传递或者调用办法都要内存拷贝,内存占用多,这时候能够思考应用指针;
  • 像 int、bool 这样的小数据类型没必要应用指针;
  • 如果须要并发平安,则尽可能地不要应用指针,应用指针肯定要保障并发平安;
  • 指针最好不要嵌套,也就是不要应用一个指向指针的指针,尽管 Go 语言容许这么做,然而这会使你的代码变得异样简单。
退出移动版