【问题标题】:Type conversion from byte slice to struct with unsafe不安全的从字节切片到结构的类型转换
【发布时间】:2019-01-06 00:02:00
【问题描述】:

我试图理解为什么我在 Go 中的代码不能像我想象的那样工作。当我执行这个测试时,它失败了:

func TestConversion(t *testing.T) {
    type myType struct {
        a     uint8
        value uint64
    }
    myVar1 := myType{a: 1, value: 12345}

    var copyFrom []byte
    copyFromHeader := (*reflect.SliceHeader)(unsafe.Pointer(&copyFrom))
    copyFromHeader.Data = uintptr(unsafe.Pointer(&myVar1))
    copyFromHeader.Cap = 9
    copyFromHeader.Len = 9

    copyTo := make([]byte, len(copyFrom))

    for i := range copyFrom {
        copyTo[i] = copyFrom[i]
    }

    myVar2 := (*myType)(unsafe.Pointer(&copyFrom[0]))
    myVar3 := (*myType)(unsafe.Pointer(&copyTo[0]))

    if myVar2.value != myVar3.value {
        t.Fatalf("Expected myVar3.value to be %d, but it is %d", myVar2.value, myVar3.value)
    }
}

输出将是:

slab_test.go:67: Expected myVar3.value to be 12345, but it is 57

但是,如果我在复制数据之前将copyFromHeader.Data 增加1,那么一切正常。像这样:

copyFromHeader.Data = uintptr(unsafe.Pointer(&myVar1)) + 1

我不明白为什么它似乎将基础数据移动了一个字节。

【问题讨论】:

    标签: go types unsafe-pointers


    【解决方案1】:

    avalue 之间有 7 个填充字节。您只能在value 中获得 12345 (57) 的最低有效字节。当您将copyFrom 向下移动一个字节时,myVar2.valuemyVar3.value 的值都是 48(12345 的第二个字节),因此您的测试通过了。如果您将 9 更改为 16,它应该可以工作。

    您以这种方式复制结构有什么特殊原因吗?

    【讨论】:

    • 非常感谢,你说得对!我们试图将一个带有uintuint8 的简单结构放入我们从syscall.Mmap 返回的字节片中。但是当我们尝试将该字节切片转换回结构时,我们应该遇到了这个问题。
    猜你喜欢
    • 2020-06-08
    • 1970-01-01
    • 2021-01-27
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 2020-09-12
    • 1970-01-01
    相关资源
    最近更新 更多