【问题标题】:How does go implement Generic in built-in type like map and slice? [closed]go 如何在 map 和 slice 等内置类型中实现 Generic? [关闭]
【发布时间】:2021-08-15 13:14:22
【问题描述】:

我们知道,我们可以声明所有类型的 map 和 slice,比如 []string, []int, []interface{}
这已经是某种泛型了。

不知道它是如何实现的?
是不是就像interface{}一样,存储typevalue,就像用void*在c语言中实现Generic一样?

【问题讨论】:

  • 我猜编译器会生成一些机器。以地图为例,你可以看到mapaccess接收到一组非常特殊的参数,并输出一个unsafe.Pointer cs.opensource.google/go/go/+/refs/tags/go1.16.7:src/runtime/…
  • 处理类型修饰符“slice”(注意 slice 本身不是类型,对于某些类型 T,它始终是“T 的切片”,这就是它是“修饰符”的原因) 在编译器内部。编译器将[]T 视为类型,并在需要函数调用时插入适当的必要函数调用,或在适合内联代码时插入内联代码。这与直接在编译器中处理int vs uint64 vs float32 相同:我们确保生成正确的代码。这就是语言的全部内容。
  • 实现方面,事情变得更加有趣:为了避免编写多个不同的地图访问器、切片构建器等,我们希望运行时系统是能够访问编译器为运行时系统留下的信息。因此,运行时系统本身与编译器本身绑定(弱绑定或强绑定,具体取决于我们希望将其绑定到何种程度)。在像 C++ 这样的“成熟”语言中,我们倾向于发现 CPU 制造商定义 ABI,以便 C++ 编译器可以调用英特尔提供的库。
  • 在快速发展的语言中,比如 Go 已经有好几年了,ABI 往往不太常见,运行时通常与特定的编译器版本更紧密地联系在一起。这使得提供新的更快的编译器变得更容易(编译速度更快,或运行速度更快,以更可取的为准),即使这意味着您不能将新编译器与现有的编译目标代码一起使用。
  • Go 构建系统本身鼓励“整个源代码随时可访问”的编译模型,这进一步避免了 C++ ABI 倾向于产生的那种僵化。不过,每种方法都有优缺点。

标签: go


【解决方案1】:

Gopher Academy youtube 频道中找到了相关的解释,Keith Randall 解释了地图以及如何实现它以拥有许多没有泛型的类型。

视频链接 - Keith Randall - Inside the Map Implementation

正如您在src/runtime/type.go 中所描述的那样,类型信息由_type 处理。

type _type struct {
    size       uintptr
    ptrdata    uintptr // size of memory prefix holding all pointers
    hash       uint32
    tflag      tflag
    align      uint8
    fieldAlign uint8
    kind       uint8
    // function for comparing objects of this type
    // (ptr to object A, ptr to object B) -> ==?
    equal func(unsafe.Pointer, unsafe.Pointer) bool
    // gcdata stores the GC type data for the garbage collector.
    // If the KindGCProg bit is set in kind, gcdata is a GC program.
    // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    gcdata    *byte
    str       nameOff
    ptrToThis typeOff
}

*_type 用于描述 go map、切片、数组、通道中的键和元素类型。

参考 := maptype, slicetype

【讨论】:

  • 不错的答案,谢谢!所以它仍然是某种运行时泛型,像 c 中那样存储值和类型,而不是像 c++ 中的模板那样的构建时泛型。
猜你喜欢
  • 2022-06-15
  • 2018-09-21
  • 2021-12-07
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
  • 2011-01-07
  • 1970-01-01
相关资源
最近更新 更多