乐趣区

关于golang:译|There-Are-No-Reference-Types-in-Go

有一天,我用谷歌搜寻一个 Go 问题,谷歌将我疏导到  Go FAQ 页面。问题解决后,我浏览了整个 FAQ。

这是一次很棒的浏览,我从文章中学到了很多。但我留神到一个问题,为什么数组是值, 而 map、slice 和 channel 是援用?回答如下:

此话题历史长远。在晚期,map 和 channel 都是语法指针,不能申明和应用非指针实例。此外,咱们在全力以赴摸索数组如何工作。最终,咱们认为指针和值的严格拆散使语言更难应用。将这些类型更改为对关联的共享数据结构的援用,就解决了这些问题。扭转给语言减少了一些令人遗憾的复杂性,但却对可用性产生了很大的影响:Go 一经推出,就成为了一种更高效、更难受的语言。

令我诧异的是,Go 官网文档仍在应用“援用类型”的概念,因为自 2013 年 4 月 3 日以来,“援用类型”的概念已从 Go 标准中齐全删除。当初 Go 标准中有 10 个“援用”词,没有一个代表“援用类型”的概念。

另一个惊喜是这句话:

… 指针和值的严格拆散使该语言更难应用。…

此回答将指针和值视为两个不兼容的概念。然而,Go 标准将指针视为非凡值,指针被称为“指针值”。值只是类型的实例。显然,Go 标准中“指针”一词的定义很好。我认为如果应用“指针值和非指针值”会更好。

所以,我认为此回答给 Go 社区带来了很多困惑。它与以后 Go 标准抵触,并且突破了概念的一致性。

谈回第一个惊喜,我认为称说   map/slice/channel 值为援用值齐全没有必要。不仅因为“reference”这个词在编程世界中被滥用了,还因为 map/slice/channel 值只是一般的正常值

以下是 map/slice/channel 类型的外部申明:

Type Family Type Declaration
map struct {m *internalHashtable}
channel struct {c *internalChannel}
slice struct {array *internalArray; len   int; cap   int}

请留神,下面的申明可能不齐全与官网或非官方的 Go 实现中的申明雷同。Go 实现能够间接应用指针示意 map 和 channel 的值,但 Go 标准 / 编译器永远不会将它们视为指针。因而,你能够释怀的将 map/slice/channel 类型视为下面申明的指针包装类型,而不会有任何问题。

从下面的申明,很容易得出结论:map/slice/channel 只是蕴含一个非导出指针字段的构造类型。将它们称为援用类型是齐全没有必要的。

Map 和 slice 类型与个别构造类型的确有一个区别。与个别构造类型不同,对于 map 或 slice 类型 T,T{}  不是 T 的零值。但这不是将 map 或 slice 类型拆分为新的援用类型类别的好理由。

通过了解 Go 的以下两个规定:

  • map/slice/channel 值只是一般的指针包装构造的值
  • 所有赋值,包含参数传递等,都是浅值复制(指针指向的值不会被复制)

Gopher 应该分明地了解赋值中的 dest 和 source  map/slice/channel 值将共享被包装的指针所指向的同一底层数据。

概念是用来帮忙程序员了解语言的机制,而不是混同他们。值、指针值和非指针值的概念足以让 Gopher 了解 Go。

我心愿 Go 文档不会毁坏概念定义的一致性。

本文作者 :cyningsun
本文地址 :https://www.cyningsun.com/08-…
版权申明:本博客所有文章除特地申明外,均采纳 CC BY-NC-ND 3.0 CN 许可协定。转载请注明出处!

退出移动版