先说清楚,在 go 中没有引用变量,所以更不存在什么引用传值了。

什么是引用变量

在类 C++ 语言中,你可以声明一个别名,给一个变量安上一个其他名字,我们把这称为引用变量。

#include int main() { int a = 10; int &b = a; int &c = b; printf("%p %p %p", &a, &b, &c); // 0x7ffe114f0b14 0x7ffe114f0b14 0x7ffe114f0b14 return 0;}

你可以看到 a,b,c 都指向同一块内存地址,三者的值相同,当你要在不同范围内声明引用变量(即函数调用)时,此功能很有用。

Go 中不存在引用变量

与 C++ 不同的是,Go 中的每一个变量都有着独一无二的内存地址。

package mainimport "fmt"func main() { var a, b, c int fmt.Println(&a, &b, &c) // 0x1040a124 0x1040a128 0x1040a12c}

你不可能在 Go 程序中找到两个变量共享一块内存,但是可以让两个变量指向同一个内存。

package mainimport "fmt"func main() { var a int var b, c = &a, &a fmt.Println(b, c)   // 0x1040a124 0x1040a124 fmt.Println(&b, &c) // 0x1040c108 0x1040c110}

在这个例子中,b 和 c 拥有 a 的地址,但是 b 和 c 这两个变量却被存储在不同的内存地址中,更改 b 的值并不会影响到 c。

map 和 channel 是引用吗

不是,map 和 channel 都不是引用,如果他们是的话,下面这个例子就会输出 false

package mainimport "fmt"func fn(m map[int]int) { m = make(map[int]int)}func main() { var m map[int]int fn(m) fmt.Println(m == nil)}

如果是引用变量的话,main 中的 m 被传到 fn 中,那么经过函数的处理 m 应该已经被初始化了才对,但是可以看出 fn 的处理对 m 并没有影响,所以 map 也不是引用。

map 是一个指向 runtime.hmap 结构的指针,如果你还有疑问的话,请继续阅读下去。

map 类型是什么

当我们这样声明的时候。

m := make(map[int]int)

编译器将其替换为调用 map.go/makemap[1]

// makemap implements Go map creation for make(map[k]v, hint).// If the compiler has determined that the map or the first bucket// can be created on the stack, h and/or bucket may be non-nil.// If h != nil, the map can be created directly in h.// If h.buckets != nil, bucket pointed to can be used as the first bucket.func makemap(t *maptype, hint int, h *hmap)*hmap

可以看到,makemap 函数返回 *hmap,一个指向hmap[2]结构的指针,我们可以从 go 源码中看到这些,除此之外,我们还可以证明 map 值的大小和 uintptr 一样。

package mainimport ( "fmt" "unsafe")func main() { var m map[int]int var p uintptr fmt.Println(unsafe.Sizeof(m), unsafe.Sizeof(p)) // 8 8 (linux/amd64)}

如果 map 是指针的话,它不应该返回 *map[key]value 吗

这是个好问题,为什么表达式 make(map[int]int) 返回一个 map[int]int 类型的结构?不应该返回 *map[int]int 吗?

Ian Taylor 在这个回答[3]中说:

In the very early days what we call maps now were written as pointers, so you wrote *map[int]int. We moved away from that when we realized that no one ever wrote mapwithout writing *map.

所以说,Go 把 *map[int]int 重命名为 map[int]int


go 如何将int设成nil_Go 中没有引用传递?相关推荐

  1. java中是引用传递还是值传递....

    刚才与Z师兄聊天,他提问: 你说java中是引用传递还是值传递啊? 当时俺搞混了这个"传递"的意思, 本来以为是对象的实例化比如: abc a=new abc(); 这个a 是引用 ...

  2. python中、变量指向的对象可以发生变化吗_python中的引用传递,可变对象,不可变对象,list注意点...

    python中的引用传递 首先必须理解的是,python中一切的传递都是引用(地址),无论是赋值还是函数调用,不存在值传递. 可变对象和不可变对象 python变量保存的是对象的引用,这个引用指向堆内 ...

  3. c+ 引用传递坑_了解C ++中的引用传递

    c+ 引用传递坑 介绍 (Introduction) In this tutorial, we are going to discuss the concept of pass by referenc ...

  4. Java方法中的引用传递

    Java方法中的引用传递 背景 基础知识 探究 定义Person类 写定义测试类进行测试 运行结果 分析 另一个例子 运行结果 分析和结论 背景 最近复习java相关的知识,看到有一个资料里写道:Ja ...

  5. error LNK2019: 无法解析的外部符号 WinMain,该符号在函数 int __cdecl invoke_main(void)”中被引用

    From:https://blog.csdn.net/u012570056/article/details/74639894 一,问题描述 MSVCRTD.lib(exe_winmain.obj) : ...

  6. java引用传递_理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和 ...

  7. C#中的引用传递、值传递

    一.传递参数 既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员(方法.属性.索引器.运算符和构造函数)更改参数的值,并保持该更改. 二.传递值类型参数 值类型变量直接包含其数据,这与引 ...

  8. 请注意,java中没有引用传递

    今天在论坛上有人提了一个关于java中调用函数时有没有引用传递的问题,可谓是吵的不可开交.有人说java只有值传递,也有人说java既有值传递也有引用传递,那么java中到底有没有引用传递呢,下面我来 ...

  9. 递归中的引用传递和常引用传递

    通过递归加深引用传递和常引用传递的区别,同时加深递归回溯的过程 void process(string& str) {if (str.size() >= 5) {cout << ...

最新文章

  1. Server 2012 Hyper-v新功能之一:客户端 Hyper-V
  2. Centos 上部署jeecms注意1
  3. 华为计算产品备件查询助手
  4. 深度神经网络(DNN)损失函数和激活函数的选择
  5. Linux共享内存(二)
  6. 阿里巴巴大规模应用Flink的踩坑经验:如何大幅降低 HDFS 压力?
  7. Qt 二级菜单无法输入中文
  8. NeurlPS 2019丨微软亚洲研究院 5 篇精选论文解读
  9. python 保存pdf文件_PyPDF2读取PDF文件内容保存到本地TXT实例
  10. OpenGL ES的性能范围(OpenGL ES2.0官方文档)
  11. Android轮播图
  12. 汉字的Unicode表位置
  13. MC9S12 硬件设计
  14. AcWing 95. 费解的开关 (递归位运算 详解)
  15. python提取一段字符串中的ip地址
  16. 从C到C++ 番外const的用法
  17. 计算机一级照片可以用红底吗,告别修图软件,教你用Excel给证件照更换多种底色!方便又省钱...
  18. 使用pymysql报错:pymysql.err.InternalError: Packet sequence number wrong - got 5 expected 1
  19. C/C++编程:注入类名
  20. 多线程(一)——委托与多线程

热门文章

  1. 发送邮件 ajax,使用Ajax发送电子邮件
  2. 计算机技术在工程施工中的应用,浅析计算机技术及网络在工程施工中的应用
  3. linux mysql 安装测试_linux下安装MySQL - 1583651986的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  4. 2021年3月程序员工资统计,平均15189元,又涨了
  5. java监听上传文件,Springmvc文件上传监听详解
  6. 关于代码控制管理的一些想法
  7. 网上看到的,关于测试用例编写粒度准则
  8. 经典面试题(三):ASP.NET部分----ASP.NET 页面之间传递值的几种方式
  9. 案例:演示exception对象的使用
  10. pycharm创建python虚拟环境好处_PyCharm虚拟环境创建Django2项目一些问题的解决方案...