关于 Go 中 Map 类型和 Slice 类型的传递

Map 类型

先看例子 m1:

func main() {
m := make(map[int]int)
mdMap(m)
fmt.Println(m)
} func mdMap(m map[int]int) {
m[1] = 100
m[2] = 200
}

结果是

map[2:200 1:100]

我们再修改如下 m2:

func main() {
var m map[int]int
mdMap(m)
fmt.Println(m)
} func mdMap(m map[int]int) {
m = make(map[int]int)
m[1] = 100
m[2] = 200
}

发现结果变成了

map[]

要理解这个问题,需要明确在 Go 中不存在引用传递,所有的参数传递都是值传递。

现在再来分析下,如图:

可能有些人会有疑问,为什么途中的 m 像是一个指针呢。查看官方的 Blog 中有写:

Map types are reference types, like pointers or slices, ...

这边说 Map 类型是引用类型,像是指针或是 Slice(切片)。所以我们基本上可以把它当作是指针来看待(注意,只是近似,或者说其中含有指针,其内部仍然含有其他信息,这里只是为了便于理解),只不过这个指针有些特殊罢了。

m1 中,当调用 mdMap 方法时重新开辟了内存,将 m 的内容,也就是 map 的地址拷贝入了 m',所以此时当操作 map 时,m 和 m' 所指向的内存为同一块,就导致 m 的 map 发生了改变。

而在 m2 中,在调用 mdMap 之前,m 并未分配内存,也就是说并未指向任何的 map 内存区域。从未导致 m' 的 map 修改不能反馈到 m 上。

Slice 类型

现在看一下 Slice。

s1:

func main() {
s := make([]int, 2)
mdSlice(s)
fmt.Println(s)
} func mdSlice(s []int) {
s[0] = 1
s[1] = 2
}

s2:

func main() {
var s []int
mdSlice(s)
fmt.Println(s)
} func mdSlice(s []int) {
s = make([]int, 2)
s[0] = 1
s[1] = 2
}

不出所料:

s1 结果为

[1 2]

s2 为

[]

因为正如官方所说,Slice 类型与 Map 类型一样,类似于指针,Slice 中仍然含有长度等信息。

修改一下 s1,变成 s3:

func main() {
s := make([]int, 2)
mdSlice(s)
fmt.Println(s)
} func mdSlice(s []int) {
s = append(s, 1)
s = append(s, 2)
}

不再修改 slice 原先的两个元素,而加上另外两个,结果为:

[0 0]

发现修改并没有反馈到原先的 slice 上。

这里我们需要把 slice 想象为特殊的指针,其已经保存了所指向内存区域长度,所以 append 之后的内存并不会反映到 main() 中:

那如何才能反映到 main() 中呢?没错,使用指向 Slice 的指针。

func mdSlice(s *[]int) {
*s = append(*s, 1)
*s = append(*s, 2)
}

内存如图所示:

注意本文中内存区域分配是否连续完全随机,不影响程序,只是为了图解清晰。

Chan 类型

Go 中 make 函数能创建的数据类型就 3 类:Slice, Map, Chan。不比多说,相比读者已经能想象 Chan 类型的内存模型了。的确如此,读者可以自己尝试,这边就不过多赘述了。(可以通通过 == nil 的比较来进行测试)。

关于 Go 中 Map 类型和 Slice 类型的传递的更多相关文章

  1. Python3.x中bytes类型和str类型深入分析

    Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str和b ...

  2. java中XMLGregorianCalendar类型和Date类型之间的相互转换

    import java.text.SimpleDateFormat;import java.util.Date;import java.util.GregorianCalendar;import ja ...

  3. js中Boolean类型和Number类型的一些常见方法

    Boolean类型 Boolean类型重写了valueOf() 方法, 返回基本布尔类型值true或false,重写了toString() 方法,返回基本字符串"true" 和 & ...

  4. oracle中int类型和number类型区别

    INT类型是NUMBER类型的子类型.下面简要说明:(1)NUMBER(P,S)该数据类型用于定义数字类型的数据,其中P表示数字的总位数(最大字节个数),而S则表示小数点后面的位数.假设定义SAL列为 ...

  5. C#中枚举类型和int类型的转化

    先定义一个枚举类型 , 初中, 高中,大学 }; int ->enum int d=2; PropertyType  a=(PropertyType)d; int <- enum Prop ...

  6. Mysql 中 text类型和 blog类型的异同

    MySQL存在text和blob: (1)相同 在TEXT或BLOB列的存储或检索过程中,不存在大小写转换,当未运行在严格模式时,如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值,值被 ...

  7. java中Long类型和long类型的大小比较

    在开发过程中老犯一些低级错误,基础还得好好加强啊...... 今天遇到这样一个问题,我用 "=="来比较两个Long类型的数据,明明数值都相等,可是结果就是false,后来仔细想想 ...

  8. mysql中Numeric类型和int类型的区别

    首先记一下,Numeric数字数据只包含 数字.数字数据包括正数.负数.小数.分数和整数 例子如下: Numeric(6,2) Numeric(16,6) Numeric(16,0) 从左到右,第一个 ...

  9. mysql中varchar类型和datetime类型字段进行比较

    我是在mysql5.7版本进行比较 表a的字段order_no和表iwebshop_tmp的字段order_no一样 需要更新iwebshop_member_order表的datetime类型expi ...

随机推荐

  1. MySQL系列(二)---MySQL事务

    MySql 事务 目录 MySQL系列(一):基础知识大总结 MySQL系列(二):MySQL事务 什么是事务(transaction) 保证成批操作要么完全执行,要么完全不执行,维护数据的完整性.也 ...

  2. 【TRICK】解决锚点定位向下浮动Xpx问题

    1. 问题描述 页面滚动后,菜单栏会固定在页头,当锚点定位时,菜单会遮盖部分定位后的内容,所以需要在锚点定位后自动向下漂移Xpx. 2. 解决办法 a. 利用空div 占位,如下: <a hre ...

  3. 聊聊synchronized的锁问题

    本文不会特别深入细致地讨论synchronized,只是做一个通俗易懂的说明,以及看清一类问题的本质,希望能给大家一点启发. 问题描述 有一个类A,提供了三个方法.分别是静态同步方法,非静态同步方法, ...

  4. java对excel表格的上传和下载处理

    Excel表格文件的上传和下载,java中涉及到文件肯定会有io流的知识. 而excel文件就要涉及到poi技术,而excel的版本包括:2003-2007和2010两个版本, 即excel的后缀名为 ...

  5. ThinkPHP5.0相关

    1.tp5的下载安装 使用git克隆下面的仓库地址,这个地址下载的速度比较快,差不多两分钟的时间. 克隆tp5的应用项目: git clone https://github.com/top-think ...

  6. Django 1.9 admin 使用suit 小记

    最近项目做到了后台管理的部分.Django虽然提供了后台管理,但是界面不咋好看.所以我使用了suit.官网http://djangosuit.com/ 步骤: 1,安装suit 项目settings. ...

  7. 【某集训题解】【DAY 2 T3】与非

    题目描述 作为一名新世纪共产主义的接班人,你认识到了资本主义的软弱性与妥协性,决定全面根除资本主义,跑步迈入共产主义.但是当你即将跨入共产主义大门的时候,遇到了万恶的资本家留下的与非电路封印,经过千辛 ...

  8. websocket 70K连接测试

    websocket 70K连接测试 最近使用socket.io做了一个实时应用,实时性.稳定性还是很让人满意的.如果拿socket.io来做小型应用,综合效率应该是最高的.但是网上少有socket.i ...

  9. 01迷宫 洛谷 p1141

    题目描述 有一个仅由数字0与1组成的n×n格迷宫.若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上. 你的任务是:对于给定的迷宫, ...

  10. 利用Div+CSS(嵌套+盒模型)布局页面完整实例流程

    Div+CSS(嵌套+盒模型)布局页面完整实例流程: <!DOCTYPE html><html> <head>  <meta charset="UT ...