Go 语言没有引用类型,指针也与众不同

面向对象编程强调数据和操作绑定,方法是有状态的,本身可能会修改数据。因此编程时确定方法是否会修改原始数据尤其关键。多数从其他语言转到 Go 语言的开发者,都会首先了解 Go 语言传递参数的时候到底是 “传值” 还是 “传引用”。如果第一门开发语言是 C 语言或者 C++ 的开发者,还会区分下什么时候 “传指针”。
概念
什么是内存? 可以把内存想想为一系列单元格,一个个排列成一行,每个单元格都有一个唯一的编号。编号顺序递增,代表内存的位置,也即是内存地址。
Go 语言没有引用类型,指针也与众不同
文章图片

每个单元格都可以存放一个值,可以通过编号读取和替换单元格内的先前写入的值。
什么是变量? 糟糕的是,如果直接使用编号编程,就需要开发者自己管理内存,也难以和其他程序同时运行,极大的增加了编写大型程序的难度。
【Go 语言没有引用类型,指针也与众不同】为了解决这个问题,就需要引入“变量”的概念。变量只是编号的假名、标签或昵称。
Go 语言没有引用类型,指针也与众不同
文章图片

var a = 6 var b = a * 3

什么是指针? 而指针的值是另一个变量的编号。指针指向变量的内存地址,就像变量代表值的内存地址一样。
func main() { a := 200 b := &a *b++ fmt.Println(a) }

Go 语言没有引用类型,指针也与众不同
文章图片

什么是引用? 在 C++ 语言中,为现有变量声明别名,称为引用变量。如代码所示,a、b、c 三个变量均共享同一内存地址
#include int main() { int a = 10; int &b = a; int &c = b; printf("%p %p %p\n", &a, &b, &c); // 0x7ffe114f0b14 0x7ffe114f0b14 0x7ffe114f0b14 return 0; }

Go 语言没有引用类型
Go 程序可以创建指向统一内存地址的变量,但无法创建共享相同内存地址的两个变量。如代码所示,b 和 c 具有相同的值(a的地址)但是,b 和 c 的内存地址是唯一的。更新 b 的内容对 c 没有影响。
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 }

2013年4月3日,“引用类型”的概念已从 Go 规范中完全删除,现在 Go 规范中的“引用”,没有一个代表“引用类型”的概念。
指针是类型吗?
指针是类型吗?这个问题可能在 C 或 C++ 中会有比较大的分歧,但是在 Go 语言中十分明确,毫无疑问:是的。
A pointer type denotes the set of all pointers to variables of a given type, called the base type of the pointer. The value of an uninitialized pointer is nil.
既然有类型,就有类型的实例:值,类型和值是截然不同的两个概念。显然,在 Go 语言中,当谈到指针时,包含 “指针类型” 和 “指针值”。
同时,为了避免指针引入的风险, Go 语言对指针做了不少的约束,如下:
  1. 指针值不支持数学运算
var p *int p++

你不能更改指针指向的位置,除非赋值另外一个地址给它。同时也就不支持 Array-Pointer Duality。
  1. base type 不同的指针值,无法直接互相赋值
type MyInt int64 type Ta*int64 type Tb*MyInt// 4 nil pointers of different types. var pa0 Ta var pa1 *int64 var pb0 Tb var pb1 *MyInt// None of the following 3 lines compile ok. /* _ = pa0 == pb0 _ = pa1 == pb1 _ = pa0 == Tb(nil) */

  1. 返回局部变量的指针是安全的
func f() *int { i := 1 return &i }

指针总结
使用过 C/C++ 语言的开发者,习惯使用的不安全的指针是 unsafe.Pointer,而非普通的指针。
int* valFirst intptr_t valSecond void* valThird

vs
int* valFirst type intptr_t *int intptr_t valSecond unsafe.Pointer valThird

对比服用,效果更佳。
本文作者:cyningsun
本文地址: https://www.cyningsun.com/08-...
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!

    推荐阅读