什么是指针
咱们都晓得,程序运行时的数据是寄存在内存中的,每一个存储在内存中的数据都有一个编号,这个编号就是内存地址。咱们能够依据这个内存地址来找到内存中存储的数据,而内存地址能够被赋值给一个指针。咱们也能够简略的了解为指针就是内存地址。
指针的申明和定义
在 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 |
从下面表格能够看到:
- 一般变量 name 的值是微客鸟窝,寄存在内存地址为 0xc00004e240 的内存中
- 指针变量 namep 的值是一般变量的内存地址 0xc00004e240
- 指针变量 nameP 的值寄存在 内存地址为 0xc00004e360 的内存中
- 一般变量存的是数据,指针变量存的是数据的地址
var 关键字申明
咱们也能够应用 var 关键字申明
var nameP *string
nameP = &name
new 函数申明
nameP := new(string)
nameP = &name
能够传递类型给这个内置的 new 函数,它会返回对应的指针类型。
指针的操作
这里强调一下:指针变量
是一个变量,这个变量的值是 指针
(内存地址)! 指针变量
是一个变量,这个变量的值是 指针
(内存地址)! 指针变量
是一个变量,这个变量的值是 指针
(内存地址)!
-
获取指针指向的值:
只须要在指针变量钱加*
号即可取得指针变量值所对应的数据:nameV := *nameP fmt.Println("nameP 指针指向的值为:",nameV) //nameP 指针指向的值为: 微客鸟窝
-
批改指针指向的值:
*nameP = "公众号: 微客鸟窝" // 批改指针指向的值 fmt.Println("nameP 指针指向的值为:",*nameP) fmt.Println("name 变量的值为:",name) // 运行后果://nameP 指针指向的值为: 公众号: 微客鸟窝 //name 变量的值为: 公众号: 微客鸟窝
- 咱们发现 nameP 指针指向的值被扭转了,变量 name 的值也被扭转了
- 因为变量 name 存储数据的内存就是指针 nameP 指向的内存,这块内存被 nameP 批改后,变量 name 的值也被批改了。
-
通过 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
指针接收者
- 如果接收者类型是 map、slice、channel 这类援用类型,不应用指针;
- 如果须要批改接收者,那么须要应用指针;
- 如果接收者是比拟大的类型,能够思考应用指针,因为内存拷贝便宜,所以效率高。
什么状况下应用指针
- 不要对 map、slice、channel 这类援用类型应用指针;
- 如果须要批改办法接收者外部的数据或者状态时,须要应用指针;
- 如果须要批改参数的值或者外部数据时,也须要应用指针类型的参数;
- 如果是比拟大的构造体,每次参数传递或者调用办法都要内存拷贝,内存占用多,这时候能够思考应用指针;
- 像 int、bool 这样的小数据类型没必要应用指针;
- 如果须要并发平安,则尽可能地不要应用指针,应用指针肯定要保障并发平安;
- 指针最好不要嵌套,也就是不要应用一个指向指针的指针,尽管 Go 语言容许这么做,然而这会使你的代码变得异样简单。