gpt4 book ai didi

go - 通过 golang 将对象编码为字节不安全?

转载 作者:IT王子 更新时间:2023-10-29 02:10:16 26 4
gpt4 key购买 nike

func Encode(i interface{}) ([]byte, error) {
buffer := bytes.NewBuffer(make([]byte, 0, 1024))
// size := unsafe.Sizeof(i)
size := reflect.TypeOf(i).Size()
fmt.Println(size)
ptr := unsafe.Pointer(&i)
startAddr := uintptr(ptr)
endAddr := startAddr + size
for i := startAddr; i < endAddr; i++ {
bytePtr := unsafe.Pointer(i)
b := *(*byte)(bytePtr)
buffer.WriteByte(b)
}
return buffer.Bytes(), nil
}

func TestEncode(t *testing.T) {
test := Test{10, "hello world"}
b, _ := Encode(test)
ptr := unsafe.Pointer(&b)
newTest := *(*Test)(ptr)
fmt.Println(newTest.X)
}

我正在学习如何使用 golang unsafe 并编写此函数来对任何对象进行编码。我遇到两个问题,首先,剂量 unsafe.Sizeof(obj) 总是返回 obj 的指针大小?为什么它不同于 reflect.TypeOf(obj).Size()?其次,我想通过unsafe.Pointer()在TestEncode函数中遍历obj的底层字节并转换回obj,但是对象的值都损坏了,为什么?

最佳答案

首先,unsafe.Sizeof 返回需要存储类型的字节。这有点棘手,但它并不意味着需要存储数据的字节。

比如一个slice,众所周知,在32bit的机器上存储了3个4字节的int。一个 uintptr 用于底层数组的内存地址,两个 int32 用于 lencap。所以无论一个 slice 有多长或它是什么类型,一个 slice 在 32 位机器上总是占用 12 个字节。一个字符串可能使用 8 个字节:1 个 uintptr 用于地址,1 个 int32 用于 len

至于reflect.TypeOf().Size的区别,是关于接口(interface)的。 reflect.TypeOf 查看接口(interface)并获取具体类型,并报告具体类型所需的字节数,而 unsafe.Sizeof 仅返回 8 接口(interface)类型:2 uintptr 用于指向数据的指针和指向方法列表的指针。

第二部分现在已经很清楚了。其一,unsafe.Pointer 获取接口(interface)的地址,而不是具体类型。第二,在 TestEncode 中,unsafe.Pointer 正在获取 12 字节 slice “ header ”的地址。可能还有其他错误,但对于上述两个错误,发现它们毫无意义。

注意:我避免谈论 uintptrint32 的命令,不仅因为我不知道,而且因为它们没有文档记录、不安全和实现视情况而定。

注意 2:结论:不要尝试转储 Go 数据的内存。

注意 3:我将所有内容都更改为 32 位,因为 playground 正在使用它,因此更容易检查。

关于go - 通过 golang 将对象编码为字节不安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48654563/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com