系统考虑

System considerations 系统考虑

原文:[https://go.dev/ref/spec#System considerations](https://go.dev/ref/spec#System considerations)

Package unsafe - unsafe 包

​ 编译器知道的内置包unsafe,可以通过导入路径unsafe “访问,它为低级编程提供了便利,包括违反(violate)类型系统的操作。使用unsafe的包必须手动审查其类型安全,并且可能无法移植。该包提供以下接口:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package unsafe

type ArbitraryType int  // shorthand for an arbitrary Go type; it is not a real type
type Pointer *ArbitraryType

func Alignof(variable ArbitraryType) uintptr
func Offsetof(selector ArbitraryType) uintptr
func Sizeof(variable ArbitraryType) uintptr

type IntegerType int  // shorthand for an integer type; it is not a real type
func Add(ptr Pointer, len IntegerType) Pointer
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType

Pointer是一个指针类型,但是Pointer的值不能被解除引用。任何底层类型uintptr的指针或值都可以被转换为底层类型Pointer的类型,反之亦然。在Pointeruintptr之间转换的效果是由实现定义的。

1
2
3
4
5
6
7
var f float64
bits = *(*uint64)(unsafe.Pointer(&f))

type ptr unsafe.Pointer
bits = *(*uint64)(ptr(&f))

var p ptr = nil

AlignofSizeof函数接收任意类型的表达式x,并分别返回假设变量v的对齐方式或大小,就像v通过var v = x声明一样。

Offsetof函数接收一个(可能是括号内的)选择器s.f,表示由s*s表示的结构体中的字段f,并返回相对于该结构体地址的字段偏移量(字节)。如果f是一个嵌入字段,它必须可以通过结构体的字段在没有指针间接的情况下访问。对于带有字段f的结构体s

1
uintptr(unsafe.Pointer(&s)) + unsafe.Offsetof(s.f) == uintptr(unsafe.Pointer(&s.f))

​ 计算机体系结构可能要求内存地址被对齐;也就是说,变量的地址必须是一个因子的倍数,即变量类型的对齐方式。函数Alignof接收一个表示任何类型的变量的表达式,并返回(该类型的)变量的对齐方式,单位为字节。对于变量x

1
uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0

​ 如果T是一个类型参数,或者它是一个包含可变大小的元素或字段的数组或结构体类型,则T类型的(变量)具有可变大小。否则,大小是常量。如果对 AlignofOffsetofSizeof 的调用的实参(或 Offsetof 的选择器表达式 s.f 中的结构体 s)是恒定大小的类型,则它们是 uintptr 类型的编译时常量表达式

Add 函数将 len 添加到 ptr 并返回更新后的指针 unsafe.Pointer(uintptr(ptr) + uintptr(len))len实参必须是整数类型或无类型的常量。一个常量len实参必须可以用int类型的值表示;如果它是一个无类型的常量,则它会被赋予int类型。Pointer的有效使用规则仍然适用。

Slice 函数返回一个切片,其底层数组从 ptr 开始,其长度和容量为 lenSlice(ptr, len) 等于

1
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]

除了这样,还有一种特殊情况,如果 ptrnil 并且 len 是零,Slice 返回 nil

len实参必须是整数类型或无类型的常量。一个常量len实参必须是非负的,并且可以用int类型的值表示;如果它是一个无类型的常量,则它会被赋予int类型。在运行时,如果len是负的,或者如果ptrnillen不是0,会发生运行时恐慌

Size and alignment guarantees 大小和对齐保证

对于数值型,以下大小是有保证的:

1
2
3
4
5
6
7
type                                 size in bytes

byte, uint8, int8                     1
uint16, int16                         2
uint32, int32, float32                4
uint64, int64, float64, complex64     8
complex128                           16

以下最小对齐特性得到了保证:

  1. 对于任何类型的变量xunsafe.Alignof(x)至少是1。
  2. 对于结构体类型的变量xunsafe.Alignof(x)x的每个字段f的所有值unsafe.Alignof(x.f)中最大的一个,但至少是1。
  3. 对于数组类型的变量xunsafe.Alignof(x)与数组元素类型的变量的对齐方式相同。

​ 如果结构体或数组类型不包含大小大于0的字段(或元素),那么它的大小就是零。两个不同的zero-size变量在内存中可能有相同的地址。