请考虑以下几点:
import ( "log" "unsafe" ) type Foo struct { Bar int32 } func main() { log.Println(int(unsafe.Sizeof(Foo{}))) }
为什么确定变量的大小被认为是不安全的,而且是不安全包的一部分?我不明白为什么获取任何类型的大小都是不安全的操作,或者go使用什么机制来确定它的大小,使之成为必要。我也很想知道是否有任何替代不安全包来确定已知结构体的大小。
mec1mxoz1#
因为在Go语言中如果你需要调用sizeof,通常意味着你在直接操作内存,你不应该这么做.如果你来自C语言世界,你可能会经常使用sizeof和malloc来创建一个可变长度的数组,但是在Go语言中不需要这样做,你可以简单地使用make([]Foo, 10),在Go语言中,内存的分配是由运行时决定的。您不应该害怕在真正有意义的情况下调用unsafe.Sizeof-但是您应该问问自己是否真的需要它。即使您使用它来编写二进制格式,通常最好自己计算所需的字节数,或者使用reflect动态生成它:
sizeof
malloc
make([]Foo, 10)
unsafe.Sizeof
reflect
len()
在uintptr、int或uint上使用unsafe来确定您是在32位还是64位上运行?通常可以通过在实际需要支持大于2^31的数字的地方指定int64来避免这种情况。或者,如果您真的需要检测它,您有许多其他选项,例如构建标签或类似的东西:
uintptr
int
uint
unsafe
int64
package main import ( "fmt" ) const is32bit = ^uint(0) == (1 << 32) - 1 func main() { fmt.Println(is32bit) }
9bfwbjaz2#
从unsafe包的外观来看,这些方法在操作时并没有使用go的类型安全。https://godoc.org/unsafepackage unsafe包含了一些绕过Go语言类型安全的操作。导入unsafe的包可能是不可移植的,并且不受Go 1兼容性指南的保护。因此,从它的声音来看,不安全性在于所提供的代码类型,而不一定在于对它的特定调用
anauzrmj3#
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! }
即使您使用具有特殊形式的类型Assert,也会产生额外的布尔值;编译器执行以下操作:哈哈,没有但是在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编程语言既不安全也不错误 *。不安全包刚刚被命名为与类型安全相反的名称,当你需要摆弄比特(操纵内存中事物的表示;直接地)。
3条答案
按热度按时间mec1mxoz1#
因为在Go语言中如果你需要调用sizeof,通常意味着你在直接操作内存,你不应该这么做.
如果你来自C语言世界,你可能会经常使用
sizeof
和malloc
来创建一个可变长度的数组,但是在Go语言中不需要这样做,你可以简单地使用make([]Foo, 10)
,在Go语言中,内存的分配是由运行时决定的。您不应该害怕在真正有意义的情况下调用
unsafe.Sizeof
-但是您应该问问自己是否真的需要它。即使您使用它来编写二进制格式,通常最好自己计算所需的字节数,或者使用
reflect
动态生成它:unsafe.Sizeof
还将包括为padding添加的字节数。len()
。在
uintptr
、int
或uint
上使用unsafe
来确定您是在32位还是64位上运行?通常可以通过在实际需要支持大于2^31的数字的地方指定int64
来避免这种情况。或者,如果您真的需要检测它,您有许多其他选项,例如构建标签或类似的东西:9bfwbjaz2#
从unsafe包的外观来看,这些方法在操作时并没有使用go的类型安全。
https://godoc.org/unsafe
package unsafe包含了一些绕过Go语言类型安全的操作。
导入unsafe的包可能是不可移植的,并且不受Go 1兼容性指南的保护。
因此,从它的声音来看,不安全性在于所提供的代码类型,而不一定在于对它的特定调用
anauzrmj3#
Go语言是一种类型安全的编程语言,它不会让你做这样的事情:
即使您使用具有特殊形式的类型Assert,也会产生额外的布尔值;编译器执行以下操作:哈哈,没有
但是在C语言中,默认情况下是由你来负责,下面的程序可以编译得很好。
你会收到一些可能出错的警告,因为随着时间的推移,人们已经认识到这是一个常见的错误,但这并没有阻止你,它只是发出一个警告。
类型安全只是意味着你不能犯C程序员已经犯过一千次的同样的错误,但是 * 使用不安全包或C编程语言既不安全也不错误 *。不安全包刚刚被命名为与类型安全相反的名称,当你需要摆弄比特(操纵内存中事物的表示;直接地)。