目录

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 传值 传引用 简介相关推荐

  1. 2021-01-14python函数传参是传值还是传引用? 参数若是简单类型是传值 若是对象类型则是传引用,python是兼容两者传参方式的

    python函数传参是传值还是传引用? 首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题. ...

  2. Java传值与传引用

    基本参数类型:传值 对象类型:传引用 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实 ...

  3. 5个php实例,细致说明传值与传引用的区别

    传值:是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值 传引用 :真正的以地址的方式传递参数传递以后,行参和实参都是同一个对象,只是他们名字不同而已对行参的修改将影响实参的值 说明: 传值 ...

  4. 几句话弄清楚Java参数传值还是传引用

    最近刷题用递归解决关于树的问题的时候,在递归函数调用的时候什么时候传入值,什么时候传入引用有疑问,因为这关系到什么时候我们需要恢复现场,什么时候不需要.在网上搜索了一下,感觉这篇总结的非常简单明了,简 ...

  5. go语言接收html传值,Go语言参数传递是传值还是传引用

    本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org或者网站http://www.flysnow.org/,第一时间看后续精彩文章.觉得好的话,顺手分享到朋友圈吧,感谢支持. 对于了 ...

  6. go语言参数传递到底是传值还是传引用

    前言 哈喽,大家好,我是asong.今天女朋友问我,小松子,你知道Go语言参数传递是传值还是传引用吗?哎呀哈,我竟然被瞧不起了,我立马一顿操作,给他讲的明明白白的,小丫头片子,还是太嫩,大家且听我细细 ...

  7. 女朋友问我:小松子,你知道Go语言参数传递是传值还是传引用吗?

    前言 哈喽,大家好,我是asong.今天女朋友问我,小松子,你知道Go语言参数传递是传值还是传引用吗?哎呀哈,我竟然被瞧不起了,我立马一顿操作,给他讲的明明白白的,小丫头片子,还是太嫩,大家且听我细细 ...

  8. C++ 函数参数传递:传值,传指针,传引用

    PS:首先理解形参   实参概念.形参是在函数定义的括号内定义的专用变量,它们的目的是保存按实参传递给它们的信息,实参被列在函数调用语句的括号内. int func(int x)//x是形参 {ret ...

  9. 条款22: 尽量用“传引用”而不用“传值”

    c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它作为默认方式.除非明确指定,函数的形参总是通过 "实参的拷贝"来初始化的,函数的调用者得到的也是函数返回值的拷贝. 正 ...

最新文章

  1. 渥太华大学药学院院长Daniel Figeys团队诚邀药物-微生物组方向博士后
  2. 【ExtJS】 布局Layout
  3. 知识图谱(四)——实体识别和扩展
  4. java 基本类型 引用类型_Java中的基本类型和引用类型变量的区别
  5. Mysql命令行下实现数据的导入
  6. 《Java编程的逻辑》终于上市了!,java开发面试笔试题
  7. Fault Tolerance 要求、限制和许可
  8. Lecture 5:无模型控制
  9. Error:Could not find common.jar (android.arch.core:common:1.0.0)
  10. 冒烟测试正确名称是踩雷测试,雷区测试
  11. PPT:人工智能在物流与供应链中的应用
  12. 【小白】线性表的链式存储结构的实现(C语言版)
  13. 原神绯樱虾仙贝怎么获得
  14. 利用python自动在火狐浏览器上输入账号密码
  15. F-PointNets
  16. html名人名言页面,HTML5 纪念卡 | 名人名言卡
  17. Wikibon突破分析:数字技能差距预示IT服务支出的反弹
  18. 计算机非全日制硕士 选校,非全日制研究生如何来选择学校呢?
  19. Rootkit 之 adore-ng 模拟木马病毒
  20. 芯洲科技SCT2450Q完全替代TPS54540,车规级芯片

热门文章

  1. Go 语言编程 — GC 垃圾回收
  2. DPDK — App 的 Makefile 解析
  3. 基站定位LAC,CID转经纬度
  4. 2018.10.30-dtoj-4008-纸牌游戏(cards)
  5. isa 2006 下发布 owa
  6. 不用图片的DIV圆角(兼容各浏览器)
  7. linux grep 正则表达式
  8. Linux 文件系统结构介绍
  9. Java编程思想读书笔记--第21章并发
  10. Linux awk内部变量