簡體   English   中英

如何通過 Go 中的反射更新結構體的數組字段值?

[英]How I can update struct's array field value via reflect in Go?

我想將 struct 字段的值編輯為 interface{} 參數。 我幾乎完成了,但是當 struct 具有數組字段時,我無法修改它。 我試圖用數組值找到合適的函數,但我找不到。 這是我的代碼。

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

我使用的是 Ubuntu 18.04 和 go1.13 linux/amd64

SetBytes的文檔說:

SetBytes 設置 v 的基礎值。 如果 v 的基礎值不是一個字節片,它會發生恐慌。

底層值是恐慌消息中所述的數組。

通過將字節復制到數組來修復:

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

在操場上運行它

SetBytes適用於切片。 Name不是切片,它是一個數組[8]byte

切片和數組之間存在重要差異,您不能真正將其用於另一個。 切片具有對數組的引用,當您傳遞切片時,會將引用傳遞給后備數組。 數組就像一個結構體,當您將數組傳遞給函數時,您傳遞的是該數組的副本,而不是對它的引用。

您可以使用 reflect.Copy 來復制字節:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM