为什么 unsafe.Sizeof 被认为是不安全的?
Why is unsafe.Sizeof considered unsafe?
考虑以下因素:
import (
"log"
"unsafe"
)
type Foo struct {
Bar int32
}
func main() {
log.Println(int(unsafe.Sizeof(Foo{})))
}
为什么确定变量的大小被认为是不安全的,并且是不安全包的一部分?我不明白为什么获取任何类型的大小是不安全的操作,或者 go 使用什么机制来确定需要这样做的大小。
我也很想知道是否有任何替代 unsafe 包的方法来确定已知结构的大小。
从 unsafe 包的外观来看,这些方法的操作没有使用 go 的类型安全。
Package unsafe contains operations that step around the type safety of
Go programs.
Packages that import unsafe may be non-portable and are not protected
by the Go 1 compatibility guidelines.
因此,从它的声音来看,不安全性存在于所提供的代码类型中,不一定来自于特定的调用它
因为在 Go 中如果你需要调用 sizeof,这通常意味着你在直接操作内存,你永远不需要这样做。
如果您来自 C 世界,您可能最常使用 sizeof
和 malloc
来创建一个 variable-length 数组 - 但在去吧,你可以简单地make([]Foo, 10)
。在 Go 中,要分配的内存量由运行时处理。
你不应该害怕在真正有意义的地方调用 unsafe.Sizeof
- 但你应该问问自己是否真的需要它。
即使您使用它来编写二进制格式,您自己计算所需的字节数通常是个好主意,或者如果有任何东西使用 reflect
动态生成它:
- 在结构上调用
unsafe.Sizeof
还将包括为 padding 添加的字节数。
- 在 dynamically-sized 结构(即切片、字符串)上调用它会产生其 headers 的长度 - 您应该改为调用
len()
。
在 uintptr
、int
或 uint
上使用 unsafe
来确定您是 运行 32 位还是 64 位?您通常可以通过在实际需要支持大于 2^31 的数字处指定 int64
来避免这种情况。或者,如果您真的需要检测它,您还有许多其他选择,例如构建标签或类似的东西:
package main
import (
"fmt"
)
const is32bit = ^uint(0) == (1 << 32) - 1
func main() {
fmt.Println(is32bit)
}
考虑以下因素:
import (
"log"
"unsafe"
)
type Foo struct {
Bar int32
}
func main() {
log.Println(int(unsafe.Sizeof(Foo{})))
}
为什么确定变量的大小被认为是不安全的,并且是不安全包的一部分?我不明白为什么获取任何类型的大小是不安全的操作,或者 go 使用什么机制来确定需要这样做的大小。
我也很想知道是否有任何替代 unsafe 包的方法来确定已知结构的大小。
从 unsafe 包的外观来看,这些方法的操作没有使用 go 的类型安全。
Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
因此,从它的声音来看,不安全性存在于所提供的代码类型中,不一定来自于特定的调用它
因为在 Go 中如果你需要调用 sizeof,这通常意味着你在直接操作内存,你永远不需要这样做。
如果您来自 C 世界,您可能最常使用 sizeof
和 malloc
来创建一个 variable-length 数组 - 但在去吧,你可以简单地make([]Foo, 10)
。在 Go 中,要分配的内存量由运行时处理。
你不应该害怕在真正有意义的地方调用 unsafe.Sizeof
- 但你应该问问自己是否真的需要它。
即使您使用它来编写二进制格式,您自己计算所需的字节数通常是个好主意,或者如果有任何东西使用 reflect
动态生成它:
- 在结构上调用
unsafe.Sizeof
还将包括为 padding 添加的字节数。 - 在 dynamically-sized 结构(即切片、字符串)上调用它会产生其 headers 的长度 - 您应该改为调用
len()
。
在 uintptr
、int
或 uint
上使用 unsafe
来确定您是 运行 32 位还是 64 位?您通常可以通过在实际需要支持大于 2^31 的数字处指定 int64
来避免这种情况。或者,如果您真的需要检测它,您还有许多其他选择,例如构建标签或类似的东西:
package main
import (
"fmt"
)
const is32bit = ^uint(0) == (1 << 32) - 1
func main() {
fmt.Println(is32bit)
}