Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

go - Dynamically call method on interface{} regardless of receiver type

I'm working on a templating system written in Go, which means it requires liberal use of the reflect package. In this specific circumstance I need to be able to dynamically call a method on an interface{}. The oddity is that my reflection logic works fine as long as my data is of a known type, but not if the data is of type interface{}.

The the following example you can see that the logic in main() and Pass() is identical. The only difference is whether the data is a known type or a known type inside an interface{}

Go Play: http://play.golang.org/p/FTP3wgc0sZ

package main

import (
    "fmt"
    "reflect"
)

type Test struct {
    Start string
}

func (t *Test) Finish() string {
    return t.Start + "finish"
}

func Pass(i interface{}) {
    _, ok := reflect.TypeOf(&i).MethodByName("Finish")
    if ok {
        fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
    } else {
        fmt.Println("Pass() fail")
    }
}

func main() {
    i := Test{Start: "start"}

    Pass(i)
    _, ok := reflect.TypeOf(&i).MethodByName("Finish")
    if ok {
        fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
    } else {
        fmt.Println("main() fail")
    }
}

Upon executing this code we get the following result

Pass() fail
startfinish

Which means that my methodology for dynamically calling a method works fine except in a scenario when my object is currently in an interface{}.

If instead I do not use a pointer receiver and pass i then it works as expected.

Go Play: http://play.golang.org/p/myM0UXVYzX

This leads me to believe that my problem is that I cannot access the address of i (&i) when it is an interface{}. I've scoured the reflect package and tested things such as reflect.Value.Addr() and reflect.PtrTo() but I could not get either to work the way I needed. My hunch is that it has something to do with the fact that an interface{} is by definition a reference object.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...