Golang - 指针与引用
Posted anthony-dong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang - 指针与引用相关的知识,希望对你有一定的参考价值。
? Golang有指针 , 那么一切数据都是值传递吗 ? 都需要用户进行指针传递吗, 其实不然, 对于Go语言, 虽然有指针, 但是其也有引用传递. 是不是很绕, 因为引用传递就是指针传递哇 . 我们继续解释.
概念
在Go语言中,对于布尔变量
或数值类型
或字符串类型
或数组
以及struct
都是按照值传递的:值在传递给函数或者方法时会被复制一份,然后方法或函数使用的是复制的这份值,也就不会对原值产生什么影响。一般情况下,对于布尔变量或数值类型或字符串类型的按值传递是非常廉价的,Go语言编译器会在传递过程中进行安全优化。
对于大字符串是这样,对于数组进行值传递也是如此。为了解决可能产生的巨大代价,Go语言使用数组切片来代替数组的使用。传递一个切片的代价跟传递字符串差不多,无论该切片的长度或容量是多大。对切片进行复制修改操作也不会像字符串那样需要创建新的切片,因为切片是可变的,属于引用类型
。
因此以下就是重点 :
语言中的值传递类型有:基本数据类型,数组 , struct
特点:变量直接存储值,内存通常在栈中分配,栈在函数调用完会被释放 , 在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 , 所以他最大的好处就是不怕多线程安全性问题. 但是浪费内存
Go语言中的引用类型有:映射(map),数组切片(slice),通道(chan),接口(interface) 与 函数(func)。
他的变量默认就是指针变量, 所以不需要做&取地址. 你要是花里胡哨我也无语.
特点:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配,通过GC回收。所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。引用注定多个线程中共享一个, 容易出现多线程问题,
就以引用传递和值传递区分 , 切记别被下面带绕了,这种话分析层面不同就不一样
其实在go语言中,只存在值传递,本质上,我们可以理解函数的传递都是值传递,只不过引用类型传递的是一个指向底层数据的指针,所以我们在操作的时候,可以修改共享的底层数据的值,进而影响到所有引用到这个共享底层数据的变量。
两大操作符
操作符& : 是返回该变量的内存地址。
操作符* :是返回该指针指向的变量的值,其实就是解除变量的指针引用,返回该变量的值.
空指针 :
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
认识指针
指针这个玩意, Java里没有,其实Java里确实有指针,我们无时无刻在使用,下面我举一个例子
type People struct {
name string
sex string
age int
}
func main() {
var pp *People
// 1. 返回一个对象
person1 := People{"zhangsan", "man", 25}
fmt.Println(person1)
pp=&person1
// 2. 直接实例化一个空对象 , 返回一个指针对象
person2 := new(People)
//
pp=person2
fmt.Println(*pp)
// 2.返回一个指针对象
person3 := &People{"wangwu", "man", 25}
pp=person3
fmt.Println(*person3)
fmt.Println(*pp)
}
输出
{zhangsan man 25}
{ 0}
{wangwu man 25}
{wangwu man 25}
这里告诉大家一个技巧就是 fmt.Println()
输出中如果首位是 &
,那么它一定是一个指针类型的数据 . 但是对于默认的引用对象,不一定了,,,
函数传参是值传递 - 但是引用类型是指针传递, 不需要用户写*申明指针类型
举个例子 我们拿数组为例子 , 举例指针的用处
func main() {
// 申明数组类型
arr := [3]int{1, 2, 3}
// 原数组
fmt.Printf("指针 : %p , 数据 : %v
", &arr,arr)
// 地址传递
printSlice(&arr)
// 值传递
printSlices(arr)
// 原数组
fmt.Printf("指针 : %p , 数据 : %v
", &arr,arr)
}
func printSlice(arr *[3]int) {
// 修改数据
arr[0] = 5
fmt.Printf("指针 : %p , 数据 : %v
", arr, *arr)
}
func printSlices(arr [3]int) {
// 修改数据
arr[0] = 4
fmt.Printf("指针 : %p , 数据 : %v
", &arr, arr)
}
输出
指针 : 0xc000052140 , 数据 : [1 2 3]
指针 : 0xc000052140 , 数据 : [5 2 3]
指针 : 0xc0000521c0 , 数据 : [4 2 3]
指针 : 0xc000052140 , 数据 : [5 2 3]
参考 https://www.cnblogs.com/52php/p/6727082.html
以上是关于Golang - 指针与引用的主要内容,如果未能解决你的问题,请参考以下文章
golang - mysql 恐慌:运行时错误:无效的内存地址或 nil 指针取消引用
使用 Kotlin 在片段中引用 RecyclerView 时出现空指针错误