当前位置:网站首页>【golang学习笔记】Go语言中参数的传递是值传递还是引用传递
【golang学习笔记】Go语言中参数的传递是值传递还是引用传递
2022-07-23 21:59:00 【Vivien_oO0】
前言
Go中所有的参数传递都是值传递,是对数据进行一个拷贝。具体分为引用类型和非引用类型
非引用类型(值类型):int,string,float,bool,数组和struct;
特点:值类型变量声明后,直接存的就是对应的数据。
引用类型:指针,slice,map,channel,接口,函数等。
特点:变量存放的是一个内存地址值,这个地址值指向的空间存的才是最终的值。内存通常在堆中分配,当没有任务变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,通过GC回收。
这里我所说的值传递,意思就是引用类型在传递的时候,其实是将值实际地址,也就是当前变量所存的地址拷贝一份进行传递。
值传递
代码:
package main
import "fmt"
func main() {
var value = 3
//因为int为值类型 所以需要取地址符
fmt.Printf("modify before addr: %p value: %d\n", &value, value)
modify(value)
//再次打印
fmt.Printf("modify after main addr: %p value: %d\n", &value, value)
}
func modify(value int) {
value = 0
fmt.Printf("modify addr: %p value: %d\n", &value, value)
}
输出:
modify before addr: 0xc000018080 value: 3
modify addr: 0xc000018088 value: 0
modify after main addr: 0xc000018080 value: 3
可以发现地址两个地址不是同一个地址,并且也不会对实参进行修改
引用传递
此时我们使用slice进行举例说明
代码:
package main
import "fmt"
func main() {
value := []int{
1, 2, 3}
fmt.Printf("modify begin addr: %p value: %d\n", value, value)
fmt.Printf("modify begin addr: %p value: %d\n", &value, value)
modify1(value)
fmt.Printf("modify after addr: %p value: %d\n", value, value)
fmt.Printf("modify after addr: %p value: %d\n", &value, value)
}
func modify1(value []int) {
value[0] = 0
fmt.Printf("modify addr: %p value: %d\n", value, value)
fmt.Printf("modify addr: %p value: %d\n", &value, value)
}
结果:
modify begin addr: 0xc0000b4000 value: [1 2 3]
modify begin addr: 0xc0000a4018 value: [1 2 3]
modify addr: 0xc0000b4000 value: [0 2 3]
modify addr: 0xc0000a4078 value: [0 2 3]
modify after addr: 0xc0000b4000 value: [0 2 3]
modify after addr: 0xc0000a4018 value: [0 2 3]
可以发现
这个地址不论是实参还是函数内部地址都是相同的,而另外一个地址是不同的。
这是因为切片是一个引用类型,然后这个变量里面保存的是实际数据的地址,而在进行参数传递的时候,我们传递的是保存的地址,而不是保存这个地址的地址。也就是说我们将这个地址值传递过去了,然后函数内部开辟了一个内存将这个地址存起来了,然后我们就可以看见无论是在外面还是里面,这个传递的地址值是不变的。而保存这个地址的地址是改变的。这也是为什么是golang是值传递的原因。

所以在函数中对数据进行修改,其实是对保存地址中的数据进行修改,所以会影响到函数外。
边栏推荐
- Mqtt connection, subscription and publishing can be realized without mqtt C library
- Jedis 6 - Introduction and difference between redisson and jedis
- 如何彻底强制杀死后台无关进程?
- 程序员成长第二十六篇:如何开好每日晨会?
- Uncertainty of distributed energy - wind speed test (realized by matlab code)
- Introduction to database system fifth edition after class exercises - Chapter 1 Introduction
- ApplicationContext introduction
- lambda學習(sort後面的Comparator的使用,collection後使用Collectors.groupingBy分組)
- How to add an operator in ONEFLOW
- The simple use of ADB command combined with monkey is super detailed
猜你喜欢

Preliminary discussion on POC compilation

Openlayers instance accessible map accessible map

ADB 命令结合 monkey 的简单使用,超详细

ESP32 的 I2C 原理 & 应用入门

Construction and application progress of ten billion level knowledge map of meituan brain

初探POC编写
![[isprint function determines whether characters can be output]](/img/c8/c06dc36dbd0bf1feeba64c7753faf5.png)
[isprint function determines whether characters can be output]
![[create birthday card application]](/img/56/e04a9a20e181ad7b68b0f2d1d118bc.png)
[create birthday card application]

Apprentissage Lambda (utilisation du comparateur après tri, regroupement après collecte avec collectors.groupingby)

Yushu A1 robot dog gesture control
随机推荐
Is it safe to open a securities account online?
Comment forcer complètement le meurtre de processus indépendants de l'arrière - plan?
Golang invalid argument to intn报错的解决
Uniapp uses canvas to write a circular progress bar
LeetCode高频题53. 最大子数组和,具有最大和的连续子数组,返回其最大和
Yushu A1 robot dog gesture control
Redis常用命令对应到Redisson对象操作
Union and union all of Hana SQL
U++ 事件
Openlayers instances advanced mapbox vector tiles advanced mapbox vector maps
Basic principle of synchronized lock
如何彻底强制杀死后台无关进程?
节流和防抖的说明和实现
Altium designer—Arduino UNO原理图&PCB图(自制Arduino板)
PCL error: error c2589 "(": "::" illegal mark on the right)
Introduction to I2C Principle & Application of esp32
Postgraduate entrance examination | advanced mathematics Chapter4 indefinite integral
为了一劳永逸而写的数独
Golang invalid argument to INTN
产品生命周期,常见的项目职能,信息流 都是什么