系统考虑
3 分钟阅读
System considerations 系统考虑
原文:[https://go.dev/ref/spec#System considerations](https://go.dev/ref/spec#System considerations)
Package unsafe
- unsafe 包
编译器知道的内置包unsafe
,可以通过导入路径 “unsafe
“访问,它为低级编程提供了便利,包括违反(violate)类型系统的操作。使用unsafe
的包必须手动审查其类型安全,并且可能无法移植。该包提供以下接口:
|
|
Pointer
是一个指针类型,但是Pointer
的值不能被解除引用。任何底层类型为uintptr
的指针或值都可以被转换为底层类型Pointer
的类型,反之亦然。在Pointer
和uintptr
之间转换的效果是由实现定义的。
|
|
Alignof
和Sizeof
函数接收任意类型的表达式x
,并分别返回假设变量v
的对齐方式或大小,就像v
通过var v = x
声明一样。
Offsetof
函数接收一个(可能是括号内的)选择器s.f
,表示由s
或*s
表示的结构体中的字段f
,并返回相对于该结构体地址的字段偏移量(字节)。如果f
是一个嵌入字段,它必须可以通过结构体的字段在没有指针间接的情况下访问。对于带有字段f
的结构体s
:
|
|
计算机体系结构可能要求内存地址被对齐;也就是说,变量的地址必须是一个因子的倍数,即变量类型的对齐方式。函数Alignof
接收一个表示任何类型的变量的表达式,并返回(该类型的)变量的对齐方式,单位为字节。对于变量x
:
|
|
如果T
是一个类型参数,或者它是一个包含可变大小的元素或字段的数组或结构体类型,则T
类型的(变量)具有可变大小。否则,大小是常量。如果对 Alignof
、Offsetof
和 Sizeof
的调用的实参(或 Offsetof
的选择器表达式 s.f
中的结构体 s
)是恒定大小的类型,则它们是 uintptr
类型的编译时常量表达式。
Add
函数将 len
添加到 ptr
并返回更新后的指针 unsafe.Pointer(uintptr(ptr) + uintptr(len))
。len
实参必须是整数类型或无类型的常量。一个常量len
实参必须可以用int
类型的值表示;如果它是一个无类型的常量,则它会被赋予int
类型。Pointer的有效使用规则仍然适用。
Slice
函数返回一个切片,其底层数组从 ptr
开始,其长度和容量为 len
。Slice(ptr, len)
等于
|
|
除了这样,还有一种特殊情况,如果 ptr
是 nil
并且 len
是零,Slice
返回 nil
。
len
实参必须是整数类型或无类型的常量。一个常量len
实参必须是非负的,并且可以用int
类型的值表示;如果它是一个无类型的常量,则它会被赋予int
类型。在运行时,如果len
是负的,或者如果ptr
是nil
而len
不是0,会发生运行时恐慌。
Size and alignment guarantees 大小和对齐保证
对于数值型,以下大小是有保证的:
|
|
以下最小对齐特性得到了保证:
- 对于任何类型的变量
x
:unsafe.Alignof(x)
至少是1。 - 对于结构体类型的变量
x
:unsafe.Alignof(x)
是x
的每个字段f
的所有值unsafe.Alignof(x.f)
中最大的一个,但至少是1。 - 对于数组类型的变量
x
:unsafe.Alignof(x)
与数组元素类型的变量的对齐方式相同。
如果结构体或数组类型不包含大小大于0的字段(或元素),那么它的大小就是零。两个不同的zero-size变量在内存中可能有相同的地址。