猿问

如何通过在 GO 中反映来获取结构字段的地址

我正在编写将字节流反序列化为对象的代码,我一直在获取结构字段的指针。


基本上代码的工作方式如下:它获取指向结构的指针,然后根据它序列化它的类型,例如。如果它是一个整数,它需要接下来的 4 个字节。棘手的情况是,如果它是一个结构,因为我必须对其所有属性递归运行反序列化,而且我不知道如何获取其字段的地址以将它们传递给反序列化。


func Deserialize(objPtr interface{}, b []byte) (bytesRead int) {

    // it should be the address of the object


    val := reflect.ValueOf(objPtr).Elem()

    valPtr := reflect.ValueOf(objPtr)


    // check if either the object or *object is Serializable

    _, isSerializable := (val.Interface()).(Serializable)

    _, bo := (valPtr.Interface()).(Serializable)

    isSerializable = isSerializable || bo


    // specific type serialization

    if isSerializable{

        return objPtr.(Serializable).Deserializebyte(b)

    }


    switch val.Kind() {

    case reflect.Uint32, reflect.Int, reflect.Int32:

        res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:4]))

        valPtr.Set(res)

        return 4

    case reflect.Uint64, reflect.Int64:

        res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:8]))

        valPtr.Set(res)

        return 8

    case reflect.Struct:

        n_bytes := 0

        for i := 0; i < val.NumField(); i++ {


            // stuck in here

            valPtr.Elem()


            // I don't think the next line works

            last_n_bytes := Deserialize(&(valPtr.Elem().Field(i).Interface()), b)

            n_bytes += last_n_bytes

            b = b[last_n_bytes:]

        }

        //valPtr.Set(res)

        return n_bytes

    default:

        panic("this panic is for debug, every case should be handled above")

        res := val.Bytes()

        valPtr.Set(res)

        return len(val.Bytes())

    }

    return 0

}


千巷猫影
浏览 128回答 1
1回答

梦里花落0921

使用 reflect API 获取字段的地址:last_n_bytes := Deserialize(valPtr.Elem().Field(i).Addr().Interface(), b)该superint示例发生错误,因为应用程序通过反射 API 获取了未导出字段的地址。这是不允许的,因为它会允许另一个包修改该字段。这是一个导出字段的工作示例:type superint struct {    A int    B int}func (s *superint) lol() {}type a interface{ lol() }func main() {    i := superint{A: 1, B: 9}    valPtr := reflect.ValueOf(&i)    fmt.Printf("%v \n", &i.A)    fmt.Printf("%v \n", valPtr.Elem().Field(0).Addr().Interface())}
随时随地看视频慕课网APP

相关分类

Go
我要回答