golang 传值 传引用 简介
目录
1. 基础类型
2. struct
3. 函数
4. slice
5. map
6. chan
7. 总结
1. 基础类型
byte,int,bool,string,float,数组等均是传值。
2. struct
struct作为函数中的参数,其传递可以是传值(对象的复制,需要开辟新的空间来存储该新对象)和传引用(指针的复制,和原来的指针指向同一个对象)
建议使用指针,原因有两个:能够改变参数的值,避免大对象的复制操作节省内存。
3. 函数
函数作为参数,其本质是传函数指针,为传引用
4. slice
结论:作为函数参数时,为传引用。
数组切片的本质是一个如下的数据结构
包含一个pointer,一个长度,一个容积的结构。其中pointer指向的是作为主要存储空间的array。
那么在进行传入函数和赋值的时候,会将slice的结构复制一份,但是pointer还是指向原地址。从而实现了传引用。
注意slice扩容和不扩容的情况。
扩容情况下,切片的地址会发生变化,新增的元素不会影响到原切片;
不扩容的情况下,修改切片的元素,会同时修改原切片的对应元素,原因是指向的地址相同,会同步修改。
示例
package mainimport ("fmt"
)func appendToSlice(s []int) {fmt.Printf("in appendToSlice, 追加元素前, 切片地址: %p\n", s)s = append(s, 10)fmt.Printf("in appendToSlice, 追加元素后, 切片地址: %p\n", s)
}func alterSlice(s []int) {fmt.Printf("in alterSlice, 修改元素前, 切片地址: %p\n", s)s[0] = 10fmt.Printf("in alterSlice, 修改元素后, 切片地址: %p\n", s)
}func main() {slice1 := []int{1, 2, 3, 4, 5}slice := make([]int, 0, 5)fmt.Println(slice)fmt.Printf("slice切片地址: %p\n", slice)slice = append(slice, slice1...)fmt.Println(slice)fmt.Printf("slice切片地址: %p\n", slice)appendToSlice(slice)fmt.Println(slice)fmt.Printf("slice切片地址: %p\n", slice)alterSlice(slice)fmt.Println(slice)fmt.Printf("slice切片地址: %p\n", slice)
}
运行结果
[]
slice切片地址: 0xc000080060
[1 2 3 4 5]
slice切片地址: 0xc000080060
in appendToSlice, 追加元素前, 切片地址: 0xc000080060
in appendToSlice, 追加元素后, 切片地址: 0xc000090000
[1 2 3 4 5]
slice切片地址: 0xc000080060
in alterSlice, 修改元素前, 切片地址: 0xc000080060
in alterSlice, 修改元素后, 切片地址: 0xc000080060
[10 2 3 4 5]
slice切片地址: 0xc000080060
如果将slice := make([]int, 0, 5)改行代码替换成slice := make([]int, 0, 6),运行结果将会如下:切片不会发生扩容,地址始终没有改变
[]
slice切片地址: 0xc000080060
[1 2 3 4 5]
slice切片地址: 0xc000080060
in appendToSlice, 追加元素前, 切片地址: 0xc000080060
in appendToSlice, 追加元素后, 切片地址: 0xc000080060
[1 2 3 4 5]
slice切片地址: 0xc000080060
in alterSlice, 修改元素前, 切片地址: 0xc000080060
in alterSlice, 修改元素后, 切片地址: 0xc000080060
[10 2 3 4 5]
slice切片地址: 0xc000080060
结论
切片作为函数参数,修改函数中切片中的元素,会同步影响到原切片(不扩容,操作的内存地址相同)
切片中新增元素时,不会影响到原切片(无论有没有发生扩容均不会影响),原因:切片作为函数参数时,其len参数和cap参数均会进行复制(细节可参考文末参考资料的第二篇帖子)
不发生扩容时,底层数据原切片数据两者共享,新增数据不共享。
发生扩容时,底层数据完全独立,相互不影响。
5. map
结论:作为函数参数时,为传引用
与切片不同点在于,map的地址不管修改还是新增元素,地址都不会发生变化,因此在函数中修改的内容会同步修改到原map(其实操作的地址始终是同一块内存,当然是同步修改)
map内部维护着一个指针,该指针指向真正的map存储空间。我们可以将map描述为如下结构:
type map[key]value struct{impl *Map_K_V
}type Map_K_V struct{//......
}
6. chan
同slice和map,为传引用
7. 总结
如果对C和C++指针理解比较深的同学会发现,go里面所有的传参都是传值。
支持传引用的几个数据结构同时通过指针来维护同一个变量,从而实现传引用的,但是数据结构本身也是会被拷贝的。
golang 传值 传引用 简介相关推荐
- 2021-01-14python函数传参是传值还是传引用? 参数若是简单类型是传值 若是对象类型则是传引用,python是兼容两者传参方式的
python函数传参是传值还是传引用? 首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题. ...
- Java传值与传引用
基本参数类型:传值 对象类型:传引用 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实 ...
- 5个php实例,细致说明传值与传引用的区别
传值:是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值 传引用 :真正的以地址的方式传递参数传递以后,行参和实参都是同一个对象,只是他们名字不同而已对行参的修改将影响实参的值 说明: 传值 ...
- 几句话弄清楚Java参数传值还是传引用
最近刷题用递归解决关于树的问题的时候,在递归函数调用的时候什么时候传入值,什么时候传入引用有疑问,因为这关系到什么时候我们需要恢复现场,什么时候不需要.在网上搜索了一下,感觉这篇总结的非常简单明了,简 ...
- go语言接收html传值,Go语言参数传递是传值还是传引用
本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org或者网站http://www.flysnow.org/,第一时间看后续精彩文章.觉得好的话,顺手分享到朋友圈吧,感谢支持. 对于了 ...
- go语言参数传递到底是传值还是传引用
前言 哈喽,大家好,我是asong.今天女朋友问我,小松子,你知道Go语言参数传递是传值还是传引用吗?哎呀哈,我竟然被瞧不起了,我立马一顿操作,给他讲的明明白白的,小丫头片子,还是太嫩,大家且听我细细 ...
- 女朋友问我:小松子,你知道Go语言参数传递是传值还是传引用吗?
前言 哈喽,大家好,我是asong.今天女朋友问我,小松子,你知道Go语言参数传递是传值还是传引用吗?哎呀哈,我竟然被瞧不起了,我立马一顿操作,给他讲的明明白白的,小丫头片子,还是太嫩,大家且听我细细 ...
- C++ 函数参数传递:传值,传指针,传引用
PS:首先理解形参 实参概念.形参是在函数定义的括号内定义的专用变量,它们的目的是保存按实参传递给它们的信息,实参被列在函数调用语句的括号内. int func(int x)//x是形参 {ret ...
- 条款22: 尽量用“传引用”而不用“传值”
c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它作为默认方式.除非明确指定,函数的形参总是通过 "实参的拷贝"来初始化的,函数的调用者得到的也是函数返回值的拷贝. 正 ...
最新文章
- 渥太华大学药学院院长Daniel Figeys团队诚邀药物-微生物组方向博士后
- 【ExtJS】 布局Layout
- 知识图谱(四)——实体识别和扩展
- java 基本类型 引用类型_Java中的基本类型和引用类型变量的区别
- Mysql命令行下实现数据的导入
- 《Java编程的逻辑》终于上市了!,java开发面试笔试题
- Fault Tolerance 要求、限制和许可
- Lecture 5:无模型控制
- Error:Could not find common.jar (android.arch.core:common:1.0.0)
- 冒烟测试正确名称是踩雷测试,雷区测试
- PPT:人工智能在物流与供应链中的应用
- 【小白】线性表的链式存储结构的实现(C语言版)
- 原神绯樱虾仙贝怎么获得
- 利用python自动在火狐浏览器上输入账号密码
- F-PointNets
- html名人名言页面,HTML5 纪念卡 | 名人名言卡
- Wikibon突破分析:数字技能差距预示IT服务支出的反弹
- 计算机非全日制硕士 选校,非全日制研究生如何来选择学校呢?
- Rootkit 之 adore-ng 模拟木马病毒
- 芯洲科技SCT2450Q完全替代TPS54540,车规级芯片