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

标签 go

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/

相关文章:

golang - 使用 io.Copy 将奇怪的字符从 bufio.Reader 复制到 STDOUT

go - 获取响应行错误 - Redigo Redis Client

go - 设置 Martini 日志路径

Golang google sheets API V4 - 编写/更新示例?

javascript - Vue js axios 向 golang 服务器发出请求,Preflight 错误

import - Go中如何导入本地文件?

google-app-engine - 去数据存储查询获取单个实体?

go - 意外的代码点转换

go - ...interface{} 的含义(点点接口(interface))

javascript - Go 语言中的正则表达式 "before text matching"