先说结论

GO中只有值传递,没有引用传递

所谓值传递,就是实参通过拷贝将自身内容传递给形参。也就是将传递的内容拷贝一份,给函数。所以函数外和函数里对这个参数地址求值,应该是不一样的。

证明如下:

func main() {slice := []int{0,1,2,3}m := make(map[string]string)m["A"] = "a"var i *inta := 123i = &afmt.Printf("[main pointer] %pn", &i)fmt.Printf("[main map] %pn", &m)fmt.Printf("[main slice] %pn", &slice)get(slice, m, i)
}func get(s []int, m map[string]string, i *int)  {fmt.Printf("[get pointer] %pn", &i)fmt.Printf("[get map] %pn", &m)fmt.Printf("[get slice] %pn", &s)
}// output
[main pointer] 0xc0000ae020
[main map] 0xc0000ae018
[main slice] 0xc0000a6020
[get pointer] 0xc0000ae038
[get map] 0xc0000ae030
[get slice] 0xc0000a6040

可以发现,slice、map、指针在传递过程中,地址都发生了变化。这说明传递的是一份拷贝。

但是我们又发现,在函数里修改slice、map,函数外的值也会改变,这是为什么呢?

// main
get(slice, m, i)
fmt.Println(slice)
fmt.Println(m)
fmt.Println(*i)// get
s[1] = 9999
m["A"] = "QQQQQ"
a := 999
i = &a// output
[0 9999 2 3] // 修改之前为 []int{0,1,2,3}
map[A:QQQQQ] // 修改之前为 m["A"] = "a"
123          // 修改之前为 *i = 123

这就必须说到slice、map的存储结构了。以slice为例

slice 存储结构

slice结构主要包括3个部分:data、len、cap。结构中的len和cap分别指示元素数量和容量。append使得len变大,但如果append之后的元素个数大于cap,会引发扩容机制。此时,会重新创建一个容量适合的底层数组data为指针,指向底层数组。

所以slice本质上指的就是这个结构(data+len+cap,不包括底层的数组)。在参数传递过程中,这个结构拷贝了一份,data指向的还是原来的底层数组。当我们对slice中的元素进行修改时,还是会通过拷贝之后的data,直接对底层数组进行修改。

go 中,slice、map、channel都是引用类型,所以都会有如上的特性。

由于slice在扩容的过程中,会重新创建底层数组,data指向新的数组。那么,我们可以推测,在get函数中如果能触发扩容,那么修改新的底层数组,并不会对main中的slice造成影响。是否这样呢?

func main() {slice := []int{0,1,2,3}fmt.Printf("[main slice] %pn", &slice)get(slice)fmt.Printf("[new slice] %vn",slice)
}func get(s []int)  {fmt.Printf("[get slice] %pn", &s)s = append(s, 9999)
}// output
[main slice] 0xc0000a6020
[get slice] 0xc0000a6040
[new slice] [0 1 2 3]

果然如此!那么就很清楚了。

总结

1、go中函数传递都是值传递

2、slice、map、channel都是引用类型,即便是值传递,结构内部还是指向原来的引用对象,所以函数体内可以直接修改元素。

3、如果slice触发扩容,data会指向新的底层数组,而不指向外部的底层数组了。所以之后再修改slice,不会对外部的slice造成影响。

go slice获取唯一值_Go语言引用传递与值传递相关推荐

  1. ostream作为函数返回值_GO语言基础函数

    GO语言基础–函数 函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数定义 Go语言中定义函数使用func关键字,具体格式如下: func 函数名(参数 ...

  2. jsonobject修改key的值_Go 语言 map 解析之 key 的定位核心流程

    1 哈希表 哈希表属于编程中比较常见的数据结构之一,基本上所有的语言都会实现数组和哈希表这两种结构,Hash table 的历史是比较悠远的,我们在编程时也是离不开的,这种数据结构的作用其实很简单,就 ...

  3. 易语言取linux命令返回值,易语言取程序返回值写法

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:易语言取程序返回值写法回答:在易语言中,程序包括"处理程序"都有六部分组成.一.程序名,就是程序的名称,程序名不 ...

  4. c语言编程实现表达式求值,c语言实现表达式求值的方法

    c语言实现表达式求值的方法 发布时间:2020-06-22 16:45:46 来源:亿速云 阅读:82 作者:Leah 这期内容当中小编将会给大家带来有关c语言实现表达式求值的方法,以专业的角度为大家 ...

  5. python3 获取file大小_Go语言 | 你还在这样获取文件的大小吗?

    在项目中,我们可能会需要获取一个文件的大小,在Golang(Go语言)中,有很多方法来获取一个文件的大小,看看你是否还在用最慢的方式. Read字节方式 第一种,是最直观会想到的,也就是打开文件,把文 ...

  6. mysql查询唯一单词_MySql从表中获取唯一单词列表,其中字段中的值用逗号分隔

    我不确定这是否可以用纯SQL(MySQL),但无论如何我会问.我有这样一张桌子: ID TAGS ----------------------------- 1 word1,word2,word3 2 ...

  7. ostream作为函数返回值_Go语言入门必知教程-函数

    函数是为了执行特定任务而存在于程序内的一组语句,函数接受输入并返回输出. 函数允许将常用的代码块提取出来成为单个组件. 使用最广的Go函数是main(),每个独立的Go程序都必须有个main函数. 创 ...

  8. 高精度计算PI值 C语言 思路,高精度计算PI值

    高精度计算PI值 高精度计算PI值 所用公式: #include #include typedef struct list{ int data; struct list *next; struct l ...

  9. 关于值类型和引用 类型

    -----------------------------------------关于值 类型 和 引用 类型--------------------------------------------- ...

最新文章

  1. C# NPOCO 轻量级ORM框架(进阶)
  2. 用go语言制作读取excel模板批量生成word工具
  3. C++ 反转单向链表
  4. 关于web性能一些特性汇总
  5. 边缘计算 | 阿里边缘云原生平台研发工程师招聘
  6. easyui前端实现多选框_EasyUI实现下拉框多选功能
  7. 为什么上一家公司离职?
  8. linux编译命令io,Hadoop 用命令行编译URLCat
  9. C语言练习题(递归)
  10. 如何从产品和技术角度上做一个好产品----软件公司如何开源节流(二)
  11. python中show函数的用法_python学习笔记之——函数模块
  12. GPS 入门 6 —— 各国卫星导航系统比较(北斗、伽利略、GLONASS、GPS)(转)
  13. excel高级功能-分级显示
  14. matlab 两个txt文件的合并。。
  15. javascript 获取当前日期 月份 时间
  16. 计算机硬件资源如何共享,如何设置计算机共享资源
  17. python queue 查询是否在队列中_Python queue队列
  18. STM32 SPI NSS大揭秘
  19. 【Effective C++ 条款03 笔记】尽可能使用const
  20. linux学习笔记2.0

热门文章

  1. Python3面向对象编程的三大特性 封装、继承、多态
  2. C++中转换构造函数:将其它类型转换为当前类的类型
  3. java facets_Java UIComponent.getFacets方法代码示例
  4. 如何提高3D点云目标检测的难例精度?
  5. web在线阅读日志文件,response.getOutputStream().write中文乱码原因
  6. RDKit toolkit实战二:Generating Similarity Maps Using Fingerprints
  7. 可视化生信分析利器 Galaxy 之 Docker 部署
  8. ESTL:新型多重扩增子测序法可实现污水中 SARS-CoV-2 RNA 的精确定量和病毒溯源...
  9. Nature子刊:南土所贾仲君组-稻田甲烷氧化的微生物机制
  10. cap3拼接sanger序列:在线+本地分析方法实战