Go access pointer value if its passed as interface{}

huangapple go评论92阅读模式
英文:

Go access pointer value if its passed as interface{}

问题

我正在编写一个程序,需要访问作为interface{}传递的指针的值。

以下是示例代码:

package main

import (
    "reflect"
)

type Test struct {
    Names []string
}

func main() {
    arr := []string{"a", "a", "a", "a", "a", "a"}
    obj := new(Test)
    obj.Names = arr
    TestFunc(obj)
}

func TestFunc(obj interface{}) {
    rt := reflect.TypeOf(obj)
    switch rt.Kind() {
    case reflect.Struct:
        return
    case reflect.Ptr:
        TestFunc(reflect.ValueOf(obj).Elem().Interface())
    }
}

问题是,当我将指针传递给TestFunc()时,我不知道如何在函数内部访问其值。这个问题有可能解决吗?

根据传递的是指针还是其他类型,我需要执行一些操作,所以如果我继续递归地传递指针,程序将失败。我需要从传递的指针中获取值(而不是继续传递指针),但是因为我处理的是interface{}类型而不是指针,编译器不知道是否会传递指针,所以它不允许像*obj这样的操作来获取其值。

英文:

I'm writing a program where I need to access a value of a pointer which is passed as an interface{}.

playground

package main

import (
    "reflect"
)

type Test struct {
    Names []string
}

func main() {
    arr := []string{"a", "a", "a", "a", "a", "a"}
    obj := new(Test)
    obj.Names = arr
    TestFunc(obj)   
}

func TestFunc(obj interface{}){
    rt := reflect.TypeOf(obj)
    switch rt.Kind() {
        case reflect.Struct:
            return
        case reflect.Ptr:
            TestFunc(*obj)  //<<--- There is the problem, cannot figure out how to access 
//value of obj and *obj is not allowed here because of interface{} type.
    }
}

This is just a sample from a much bigger program, but it is enough to explain my problem.

So the problem is, when I pass a pointer to TestFunc() I do not know how to reach its value inside function. Is it possible at all?

I need to do some stuff based on wether it is a pointer or not, so if I keep passing pointer recursively the program will fail. I need to get the value from the passed pointer(and pass forward value instead of pointer) but I am not sure if it is possible because I am dealing with a type interface{} and not a pointer and compiler does not know if it is going to be a pointer passed so it does not allow something like "*obj" to reach the value of it.

答案1

得分: 3

如果您需要支持任意级别的指针,可以使用反射来获取值对象:

v := reflect.ValueOf(obj)
for v.Kind() == reflect.Ptr {
    v = v.Elem()
}
v.Interface()

然而,在实际应用中,这种情况相当不常见。

对于您的函数,可以这样实现:

func TestFunc(obj interface{}) {
    rv := reflect.ValueOf(obj)
    switch rv.Kind() {
        case reflect.Struct:
            // 在这里编写代码
            return
        case reflect.Ptr:
            TestFunc(rv.Elem().Interface())
    }
}
英文:

If you need to support arbitrary levels of pointers then you can use reflection to get the value object:

v:=reflect.ValueOf(obj)
for v.Kind() == reflect.Ptr {
	v = v.Elem()
}
v.Interface()

However, this is quite unusual to actually need to do in practice.

For your function, this could work as something like:

func TestFunc(obj interface{}){
    rv := reflect.ValueOf(obj)
    switch rv.Kind() {
        case reflect.Struct:
            // code here
            return
        case reflect.Ptr:
            TestFunc(rv.Elm().Interface()) 
    }
}

huangapple
  • 本文由 发表于 2017年7月27日 01:54:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/45334244.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定