Go 引用一直是我比较让疑惑的话题,尝试来聊聊它,可行呢?
之前,我一直都有些混乱,非常想整理下这个问题。我相信,除了我,还有很多人在这一块也有很多疑问。
提一些简单的问题。比如下面这些:
什么是引用呢?
引用和指针有什么区别?
Go 语言中有没有引用类型吗?
值传递、址传递和引用传递分别是什么?
是不是感觉到这是一个非常令人头疼的话题。学了那么多语言,但没有深入总结,或许就会导致这样的思维混乱。
前言
我认为,明明白白地理解引用,可分别从类型和传递思考。
类型角度的话,类型可分为值类型和引用类型,一般而言,我们说到引用,强调的都是类型。
传递角度的话,有值传递、址传递和引用传递,传递是在函数调用时才会提到的概念,用于表明实参与形参的关系。
引用类型和引用传递的关系,尝试一句话概括,引用类型不一定是引用传递,但引用传递的一定是引用类型。
简单的几句话,是在使用各种语言后总结出来的,希望无误吧,毕竟不能误导他人。
是什么
谈引用,不得不提指针,指针与引用是编程学习中老生常谈的话题了。有些编程语言为了降低程序员的使用门槛,只有引用。而有些语言是指针引用皆存在,如 C++ 和 Go。
指针,表示地址的意思。
程序运行的时候,操作系统会为每个变量分配一块内存放数据内容,而这块内存有一个编号,即内存地址,也就是变量的地址。现在 CPU 一般都是 64 位,因而,这个地址的长度一般也就是 8 个字节。
引用,某块内存的别名。
一般情况,都会这么解释引用。换句话说,引用代指某个内存地址,这句话真的是非常简洁,同时也非常好理解。但在 Go 中,这句话看起来并不全面,具体后面解释。
除了指针和引用,还有另外一个更广泛的概念,值。谈变量传递时,常会提到值传递、址传递和引用传递。从广义上看,对大部分的语言而言,指针和引用都属于值。而从狭义角度来说,则可分为值、址和引用。
脑壳疼啊?香菇,难受。感觉到自己头发在掉了。
其实,如果要想彻底搞清楚这些概念,得从本质出发啊。
值和指针
先来搞明白值与指针区别。
上一节在介绍指针的时候,提到了要注意变量的地址和内容的不同。为什么要说这句话呢?
假设,我们定义一个 int 类型的变量 a,如下:
var a int = 1
变量 a 的内容为 1,而变量内容是存在某个地址之中的。如何获取变量地址呢?Go 中获取变量地址的方法与 C/C++ 相同。代码如下:
var p = &a
通过 & 获取 a 的地址。同时,这里还定义了一个新的变量 p 用于保存变量 a 的地址。p 的类型为 int 指针,也就是变量 p 中的内容是变量 a 的地址。
如下代码输出它们的地址:
var a = 1var p = &afmt.Printf("%p