Как я могу обновить значение поля массива struct с помощью отражения в Go? - PullRequest
0 голосов
/ 20 января 2020

Я хочу отредактировать значение структурных полей в качестве параметров интерфейса {}. Я сделал почти, но когда структура имеет поле массива, я не мог изменить это. Я пытался найти правильную функцию со значением массива, но я не мог найти это. Вот мой код.

edit_struct_via _interface. go

package main

import (
    "reflect"
    "fmt"
)


type myStruct struct {
    Name    [8]byte
    TID     [4]byte
    Chksum  uint16
}

func main() {
    var s = new(myStruct)
    name := []byte("Mike")
    tid  := []byte{0x01, 0x02, 0x03, 0x05}
    setArrayField(name, s.Name[:])
    setArrayField(tid, s.TID[:])
    s.Chksum = 0x0101

    myObj := reflect.ValueOf(s).Elem()

    typeOfMyObj := myObj.Type()
    for i := 0; i < myObj.NumField(); i++ {
        f := myObj.Field(i)
        fmt.Printf("%d: %s %s = %v\n", i,
            typeOfMyObj.Field(i).Name, f.Type(), f.Interface())
    }

    newName := []byte("Emil")
    myObj.Field(0).SetBytes(newName[:])
    // I trying to change array field at here, but panic occur here.
    // Because SetBytes must been called on slice, but myObj.Field(0) is array.

    myObj.Field(2).SetUint(99)             // It works.
    fmt.Println("s is now: ", *s)
}

func setArrayField(src []byte, target []byte) {
    // retun if src is bigger than target
    if len(src) > len(target){
        return
    }

    for index, item := range src {
        target[index] = item
    }
}

Когда я запускаю над кодом, я получаю

0: Name [8]uint8 = [77 105 107 101 0 0 0 0]
1: TID [4]uint8 = [1 2 3 5]
2: Chksum uint16 = 257
panic: reflect: call of reflect.Value.SetBytes on array Value

goroutine 1 [running]:
reflect.flag.mustBe(...)
        /usr/local/go/src/reflect/value.go:208
reflect.Value.SetBytes(0x4a6180, 0xc000098010, 0x191, 0xc000098078, 0x4, 0x4)
        /usr/local/go/src/reflect/value.go:1557 +0x140
main.main()
        /home/hornet/go/src/gateway-golang/edit_struct_via _interface.go:33 +0x522
exit status 2

I использую Ubuntu 18.04 и go1.13 linux / amd64

Ответы [ 2 ]

1 голос
/ 20 января 2020

Документация для SetBytes гласит:

SetBytes устанавливает базовое значение v. Он паникует, если базовое значение v не является слайсом байтов.

Подчеркнутое значение является массивом, как указано в сообщении pani c.

Исправлено путем копирования байтов в массив:

reflect.Copy(myObj.Field(0), reflect.ValueOf(newName))

Запустите его на детской площадке .

0 голосов
/ 20 января 2020

SetBytes работает на ломтиках. Name это не фрагмент, это массив [8]byte.

Существуют важные различия между срезами и массивами, и вы не можете использовать одно для другого. Срез имеет ссылку на массив, когда вы передаете срезы, вы передаете ссылку на резервный массив. Массив похож на структуру, когда вы передаете массив функциям, вы передаете копии этого массива, а не ссылку на него.

Вы можете использовать refle.Copy для копирования байтов:

reflect.Copy(myObj.Field(0), reflect.ValueOf(newName))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...