Go被设计成一种简洁、极简的语言。因此,它从值和指针开始。后来,根据需要,添加了一些参考类型(切片、贴图和通道)。 Go编程语言:语言设计常见问题:为什么贴图、切片和通道是引用,而数组是值? “关于这个主题有很多历史。早期,map和channel在语法上都是指针,不可能声明或使用非指针示例。此外,我们还为数组应该如何工作而挣扎。最终我们认为指针和值的严格分离使得语言更难使用。引入引用类型,包括处理数组引用形式的切片,解决了这些问题。引用类型给语言增加了一些令人遗憾的复杂性,但它们对可用性有很大的影响:当Go语言被引入时,它变成了一种更高效、更舒适的语言。” 快速编译是Go编程语言的主要设计目标;这是有代价的其中一个损失似乎是将变量(除了基本的编译时常量)和参数标记为不可变的能力。有人提出要求,但被拒绝了。 golang-nuts : go language. Some feedback and doubts. “将const添加到类型系统中会强制它出现在任何地方,并强制在发生更改时将其删除。虽然以某种方式将对象标记为不可变可能有一些好处,但我们不认为const类型限定符是可行的。
6条答案
按热度按时间kzipqqlq1#
指针的用处有几个原因。指针允许控制内存布局(影响CPU缓存的效率)。在Go语言中,我们可以定义一个结构,其中所有成员都在连续的内存中:
在这种情况下,
Point
结构嵌入在LineSegment
结构中。但你不能总是直接嵌入数据。如果你想支持二叉树或链表这样的结构,那么你需要支持某种指针。Java,Python等没有这个问题,因为它不允许你嵌入复合类型,所以没有必要在语法上区分嵌入和指向。
使用Go指针解决Swift/C#结构体的问题
一个可能的替代方案是像C#和Swift一样区分
struct
和class
。但这确实有局限性。虽然通常可以指定函数将结构体作为inout
参数以避免复制结构体,但它不允许存储结构体的引用(指针)。这意味着你永远不能把一个结构体当作一个引用类型,当你发现它有用的时候,例如。创建一个池分配器(见下文)。自定义内存分配器
使用指针,你也可以创建你自己的池分配器(这是非常简化的,删除了很多检查,只是显示原理):
交换两个值
指针还允许您实现
swap
。也就是交换两个变量的值:总结
Java从来没有能够完全取代C的系统编程,部分原因是由于缺乏控制内存布局和使用的能力(缓存未命中会显着影响性能),性能无法调整到相同的程度。Go的目标是在许多领域取代C,因此需要支持指针。
vatpfxk52#
我很喜欢https://www.golang-book.com/books/intro/8的例子
区别于
pxq42qpu3#
Go被设计成一种简洁、极简的语言。因此,它从值和指针开始。后来,根据需要,添加了一些参考类型(切片、贴图和通道)。
Go编程语言:语言设计常见问题:为什么贴图、切片和通道是引用,而数组是值?
“关于这个主题有很多历史。早期,map和channel在语法上都是指针,不可能声明或使用非指针示例。此外,我们还为数组应该如何工作而挣扎。最终我们认为指针和值的严格分离使得语言更难使用。引入引用类型,包括处理数组引用形式的切片,解决了这些问题。引用类型给语言增加了一些令人遗憾的复杂性,但它们对可用性有很大的影响:当Go语言被引入时,它变成了一种更高效、更舒适的语言。”
快速编译是Go编程语言的主要设计目标;这是有代价的其中一个损失似乎是将变量(除了基本的编译时常量)和参数标记为不可变的能力。有人提出要求,但被拒绝了。
golang-nuts : go language. Some feedback and doubts.
“将const添加到类型系统中会强制它出现在任何地方,并强制在发生更改时将其删除。虽然以某种方式将对象标记为不可变可能有一些好处,但我们不认为const类型限定符是可行的。
g0czyy6m4#
引用不能被重新分配,而指针可以。仅这一点就使得指针在许多不能使用引用的情况下很有用。
mpgws1up5#
我不会在“Go”的上下文中回答这个问题,我会在任何语言的上下文中回答这个问题(例如:C、C++、Go),其实现了“指针”的概念;同样的道理也适用于“围棋”。
通常有两个存储器部分,其中进行存储器分配:堆内存和堆栈内存(让我们不包括“全局部分/内存”,因为它会脱离上下文)。
堆内存:这是大多数语言使用的:无论是Java,C#,Python..
堆栈内存:在C、C++、Go、Java等语言中,变量可以在堆栈内存中分配。堆栈内存不需要垃圾回收;因此,它是堆存储器的高性能替代方案。
但有一个问题:当我们在堆内存中分配一个对象时,我们得到一个“引用”,它可以传递给“* 多个方法/函数 ”,并且正是通过引用,“ 多个方法/函数 ”可以直接读取/更新同一个对象(在堆内存中分配)。可悲的是,堆栈内存的情况并非如此;正如我们所知,每当堆栈变量被传递给方法/函数时,它都是“按值传递”的(例如,Java),前提是你有“指针的概念”(就像C、C++、Go的情况一样)。
这里是指针进入画面的地方。指针让“ 多个方法/函数 ”读取/更新堆栈内存中的数据。
简单来说,“指针”允许使用“栈内存”代替堆内存,通过“多方法/函数”处理变量/结构/对象;因此, 避免了由垃圾收集机制引起的性能冲击 *。
在Go中引入指针的另一个原因可能是:Go应该是一种“高效的系统编程语言”,就像C,C++,Rust等一样。并与底层操作系统提供的系统调用一起顺利工作,因为许多系统调用API在其原型中具有指针。
有人可能会说,这可以通过在系统调用接口之上引入一个无指针层来实现。是的,这是可以做到的,但是有指针就像非常接近系统调用层,这是一个好的系统编程语言的特点。
jyztefdp6#
指针是特殊变量,用于存储其他变量的内存地址,并指向其内存地址,从而提供访问该地址中存储的变量值的方法。
1.我们需要指针变量的原因之一是它们很便宜,因为它们占用固定的大小,而不管它们指向的值的大小。
1.此外,我们可以使用指针来帮助内存管理来增加变量的生存期,而不依赖于它的作用域。