Golang:使用反射获取指向结构的指针

我正在尝试编写递归遍历结构并跟踪指向其所有字段的指针以进行基本分析(大小、引用数量等)的代码。但是,我遇到了一个问题,我似乎无法得到反射来给我指向纯结构的指针。我以下面的代码为例:


type foo struct {

    A    *bar

    data []int8

}


type bar struct {

    B       *foo

    ptrData *[]float64

}


func main() {

    dataLen := 32

    refData := make([]float64, dataLen)


    fooObj := foo{data: make([]int8, dataLen)}

    barObj := bar{

        B:       &fooObj,

        ptrData: &refData,

    }

    fooObj.A = &barObj


    fooVal := reflect.ValueOf(fooObj)

    _ := fooVal.Addr().Pointer() // fails

    _ := fooVal.Pointer() // fails


    // More analysis code after this

}

如果我想穿越fooObj,那就好了,直到我进入barObj,然后我又遇到了fooObj。因为第一次fooObj遇到的指针没办法拿到,最后遍历fooObj了两次,直到碰到barObj第二次才退出递归。知道如何使用反射获取结构的指针吗?


收到一只叮咚
浏览 187回答 3
3回答

一只斗牛犬

package mainimport (    "reflect"    "fmt")type foo struct {    A    *bar    data []int8}type bar struct {    B       *foo    ptrData *[]float64}func main() {    dataLen := 32    refData := make([]float64, dataLen)        // allocate here, now value has a pointer    fooObj := &foo{data: make([]int8, dataLen)}     barObj := bar{        B:       fooObj,        ptrData: &refData,    }    fooObj.A = &barObj    fooVal := reflect.ValueOf(fooObj)    fmt.Println(fooVal.Pointer()) // succeeds    // More analysis code after this}Addr 返回一个指针值,表示 v 的地址。如果 CanAddr() 返回 false,它会崩溃。Addr 通常用于获取指向结构字段或切片元素的指针,以便调用需要指针接收器的方法。

开满天机

如果可能的话,这需要一个值的指针。package mainimport "reflect"import "fmt"func main() {    val := new(int)    slice := []int{}    local := 10    fn := func() {}    fmt.Println(PointerOf(val))    fmt.Println(PointerOf(slice))    fmt.Println(PointerOf(&local))    fmt.Println(PointerOf(fn))    fmt.Println(PointerOf(3))}func PointerOf(value any) (p uintptr, ok bool) {    rValue := reflect.ValueOf(value)        if(rValue.Kind() == reflect.Pointer || rValue.Kind() == reflect.Slice || rValue.Kind() == reflect.Func) {        return rValue.Pointer(), true    }        if(rValue.CanAddr()) {        return rValue.Addr().Pointer(), true    }    return}

holdtom

正如您所提到的,您的代码在这部分失败了fooVal := reflect.ValueOf(fooObj)_ = fooVal.Addr().Pointer() // fails_ = fooVal.Pointer() // failsIn foostructdata不是指针值。type foo struct {    A    *bar    data []int8}您正在尝试在非指针类型上调用reflect.Value.Addr().Pointer()and ,从而导致错误。reflect.Value.Pointer()您可以通过检查类型是否实际上是来防止这种情况ptrpackage mainimport (    "reflect")type foo struct {    A    *bar    data []int8}type bar struct {    B       *foo    ptrData *[]float64}func main() {    dataLen := 32    refData := make([]float64, dataLen)    fooObj := foo{data: make([]int8, dataLen)}    barObj := bar{        B:       &fooObj,        ptrData: &refData,    }    fooObj.A = &barObj    fooVal := reflect.ValueOf(fooObj)    if fooVal.Kind().String() == "ptr" {        _ = fooVal.Addr().Pointer() // ok        _ = fooVal.Pointer()        // ok       // More analysis code for pointer types    } else {       // More analysis code for non-pointer types    }}
打开App,查看更多内容
随时随地看视频慕课网APP