为什么unsafe.Sizeof被认为是不安全的?

7
考虑以下内容:
import (
    "log"
    "unsafe"
)

type Foo struct {
    Bar int32
}

func main() {
    log.Println(int(unsafe.Sizeof(Foo{})))
}

为什么确定变量大小被认为是不安全的,并且是unsafe包的一部分?我不理解为什么获取任何类型的大小都是一项不安全的操作,或者go使用什么机制来确定其大小,需要这样做。

我还想知道是否有其他替代方案可以用于确定已知结构体的大小,而不使用unsafe包。


1
提示:如果你想要某个值的大小,可以使用reflect来避免需要导入和使用unsafe,例如reflect.TypeOf(Foo{}).Size() - icza
1
Rob Pike本人提出了一个问题,建议将Sizeof移出unsafe。 https://github.com/golang/go/issues/5602 - leaf bebop
3个回答

9

在Go语言中,如果需要调用sizeof函数,通常意味着您正在直接操作内存,而您不应该这样做。

如果您来自C语言世界,您可能经常使用sizeofmalloc一起创建可变长度的数组 - 但在Go语言中,这是不必要的,因为可以简单地使用make([]Foo, 10)。在Go语言中,要分配的内存量由运行时负责。

当真正有意义时,您不应该害怕调用unsafe.Sizeof - 但您应该问自己是否真的需要它。

即使您将其用于编写二进制格式,通常最好通过自己计算所需的字节数,或者使用reflect动态生成:

  • 调用 unsafe.Sizeof 函数时,对于一个结构体,它也会包括 填充字节 的数量。
  • 对于动态大小的结构体(如切片、字符串),调用该函数将返回它们头部的长度 - 此时应该调用 len() 函数。

想要通过使用 unsafe 包中的 uintptrintuint 类型来确定你是否在 32 位或 64 位上运行?你通常可以通过在需要支持大于 2^31 的数字时指定 int64 来避免这种情况。或者,如果你真的需要检测到这一点,还有许多其他选项,例如构建标签或像这样的东西:

package main

import (
    "fmt"
)

const is32bit = ^uint(0) == (1 << 32) - 1

func main() {
    fmt.Println(is32bit)
}

2
从unsafe包的外表来看,这些方法在其操作中不使用go的类型安全性。请参考以下链接:https://godoc.org/unsafe
包unsafe包含了绕过Go程序类型安全的操作。导入unsafe的包可能是不可移植的,并且不受Go 1兼容性指南的保护。
因此,从听起来的样子来看,不安全性在于提供的代码类型,而不一定是在特定的调用中。

1

Go是一种类型安全的编程语言。它不会让你做这样的事情:

package main

type Foo = struct{ A string }
type Bar = struct{ B int }

func main() {
    var foo = &Foo{A: "Foo"}
    var bar = foo.(*Bar) // invalid operation!
    var bar2, ok = foo.(*Bar) // invalid operation!
}

即使您使用带有额外布尔值的特殊形式的类型断言,编译器也会说:“哈哈,不行。”
但在像C这样的编程语言中,默认情况是假定您负责。下面的程序将编译得很好。
typedef struct foo {
    const char* a_;
} foo;

typedef struct bar {
    int b_;
} bar;

int main() {
    foo f;
    f.a_ = "Foo";
    bar* b = &f; // warning: incompatible pointer types
    bar* b2 = (bar*)&f;
    return 0;
}

你会收到警告,因为这些事情可能是错误的,因为人们随着时间的推移已经学会了这是一个常见的错误,但它并没有阻止你。它只是发出一个警告。

类型安全只意味着你不能犯C程序员已经犯过一千次的同样的错误,但是使用不安全的包或C编程语言既不是不安全也不是错误。不安全的包只是与类型安全相对而命名的,当你需要玩弄位(直接操作内存中的东西的表示方式)时,它恰好是正确的工具。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接