Я пытаюсь понять, почему мой код на 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(©From))
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(©From[0]))
myVar3 := (*myType)(unsafe.Pointer(©To[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
Я не понимаю, почему кажется, что базовые данные сдвигаются на один байт.
Между a
и value
есть 7 байтов заполнения. Вы получаете только младший байт из 12345 (57) в value
. Когда вы перемещаете copyFrom
на один байт вниз, значения myVar2.value
и myVar3.value
равны 48 (второй байт из 12345), поэтому ваш тест проходит. Он должен работать, если вы измените 9 на 16.
Есть ли какая-то конкретная причина, по которой вы копируете структуру таким образом?
Большое вам спасибо, вы правы! Мы пытаемся поместить простую структуру с
uint
иuint8
в байтовый фрагмент, который мы получили отsyscall.Mmap
. Но когда мы попытались вернуть этот байтовый фрагмент обратно в структуру, должно быть, мы столкнулись с этой проблемой.