How to check if interface specifies method using reflection - reflection

I want to reflect to determine whether or not a Go interface contains certain method signatures. I've dynamically got the names and signatures, previously through reflection on a struct. Here's a simplified example:
package main
import "reflect"
func main() {
type Mover interface {
TurnLeft() bool
// TurnRight is missing.
}
// How would I check whether TurnRight() bool is specified in Mover?
reflect.TypeOf(Mover).MethodByName("TurnRight") // would suffice, but
// fails because you can't instantiate an interface
}
http://play.golang.org/p/Uaidml8KMV. Thanks for your help!

You can create a reflect.Type for a type with this trick:
tp := reflect.TypeOf((*Mover)(nil)).Elem()
That is, create a typed nil pointer and then get the type of what it points at.
A simple way to determine if a reflect.Type implements a particular method signature is to use its Implements method with an appropriate interface type. Something like this should do:
type TurnRighter interface {
TurnRight() bool
}
TurnRighterType := reflect.TypeOf((*TurnRighter)(nil)).Elem()
fmt.Println(tp.Implements(TurnRighterType))

Related

Setting a value via an interface in go

In the following example, I'd like to call the setvalue() of the b object via an interface procedure.
I'd like to use an interface because I need to insert different kinds of objects in a list, possibly very big, each obeying a common interface.
However the compiler complains with the following error :
./tests.go:27:6: cannot use newbox(3) (type box) as type container in assignment:
box does not implement container (setValue method has pointer receiver)
Probably I have to define the interface differently, but how?
I know I could transform the setvalue procedure in a function, returning the updated box, but since the object can be very large, and he procedure will be called several times, i'd like to pass the object via a pointer.
Really isn't there a way to define an interface method that receive the calling structure via a pointer?
package main
import "fmt"
type container interface {
setValue (val int)
}
//--------------------------------------
// box is a kind of container
type box struct {
value int
}
func newbox (x int) box {
return box {x}
}
func (cnt *box) setValue(val int) {
(*cnt).value = val
}
// -----------------------------------------------
func main() {
var b container = newbox(3) // HERE IS THE ERROR
fmt.Printf("%v\n",b)
b.setValue(5)
fmt.Printf("%v\n",b)
}

Interface can not call self method

I have defined two functions. When I pass a pointer to it, I can't get the defined method. Why is this?
type Visitor interface {
work()
}
func test(v *Visitor) {
v.work() // error
}
func test1(v Visitor) {
v.work() // ok
}
Error:
v.work undefined (type *Visitor is pointer to interface, not
interface)
anyone know why, ths
func test(v *Visitor) {
v.work() // error
}
v.work() ought to be a method call. But v is of type *Visitor, a pointer to interface. A pointer to interface has 0 methods, it does not implement anything (except the empty interface interface{}).
When using a non-pointer, the value v (or rather its type) has a method work(), so you can call that:
func test(v Visitor) {
v.work() // ok
}
Here v.work() works, because the v is of type Visitor which is an interface, and it contains the method work().
What may be confusing is that if you add method to a (non-pointer, non-interface) concrete type, the respective pointer type will also have that method, and you can call that. This is in Spec: Method sets:
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing embedded fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.
The difference is that you tried the same with interface type, which won't work. It works with concrete (non-interface) types. Lesson is to never use pointer to interface unless you can reason why it is needed (it is rarely needed).
As the error clearly states:
v.work undefined (type *Visitor is pointer to interface, not
interface)
This is because the work() function is called on pointer to the receiver but defined on value.
type Visitor interface {
work()
}
But you are passing pointer type receiver in second case in which you are getting an error.
In Golang spec Method sets are defined as:
A type may have a method set associated with it. The method set of an
interface type is its interface. The method set of any other type T
consists of all methods declared with receiver type T. The method set
of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T). Further rules apply to structs containing embedded fields,
as described in the section on struct types. Any other type has an
empty method set. In a method set, each method must have a unique
non-blank method name.
One approach you can do is Implement the interface by using the struct on which you can call the method work().
package main
import "fmt"
type Visitor struct{}
type Visit interface {
work()
}
func test(v Visit) {
v.work() // error
fmt.Printf("%+v", v)
}
func (v *Visitor) work(){}
func main(){
v := Visitor{}
test(&v)
}
Working Code on Go playground

How to pass by address to function that takes interface

I have a Character interface defined like:
type Character interface {
SomeFunction()
}
And a Player struct defined like:
type Player struct{}
func (r *Player) SomeFunction() { }
// Some fields and other functions....
Suppose I have a function defined as
func TakeInterface(characterValue Character) {
// Do something
}
The catch is, I want to pass in characterValue as a Player by address so that changes made to it will be made to the Player the caller passed in. In Java and C++, this is easy, but I can't seem to figure it out in Golang. I've tried something like,
func TakeInterface(characterValue &Character) {
// Do something that changes characterValue
}
and then passing in a Player pointer, but then I get the error *Character.Character is pointer to interface, not interface when I try to pass in an address.
How do I go about passing a Player by address to a function that takes a Character/Character pointer? I've been looking around but with no success. Thanks!
Have you tested your code? I'm guessing no, because it works the way you expect it to work. Just pass a pointer to a player when calling the function.
func main() {
p := new(Player)
TakeInterface(p)
}
Or
func main() {
p := Player{0}
TakeInterface(&p)
}
In go you can use a type or a pointer to a type as an argument to a function that takes an interface because both satisfy the interface. You can do both:
var p1 Player
p1.SomeFunction()
var p2 *Player
p2.SomeFunction()
You should do the tour of go: https://tour.golang.org/methods/10
Here is the whole code: https://play.golang.org/p/iQIChLCziG

Go reflect with gorm library

I am using gorm package (https://github.com/jinzhu/gorm) as my database library in golang. I have many classes (database tables) like "Hotel" or "Package". Duplicating code is not good programming practice. As a silly example - lets assume I want to get first object from each table. I can write this method (GetFirstHotel, GetFirstPackage...) for each object. But better way would be to have just a single method GetFirstItem, where I would use first param to create object with same class as parameter, then pass it to gorm, which will fill it with data from database, then return it as interface{}. I tried to use reflect for that, but failed, because I probably don't understand it much.
Maybe I just didn't discover some function in gorm library, or I can't use reflect package properly. How should I implement GetFirstItem function. Is it possible to have this implemented, or should I rather repeat my code?
package main
import (
"github.com/jinzhu/gorm"
)
var db gorm.DB
type Hotel struct {
ID int64
Name string
Lat float64
Lon float64
}
type Package struct {
ID int64
Name string
Text string
}
func GetFirstHotel() (hotel Hotel) {
db.First(&hotel)
}
func GetFirstPackage() (pack Package) {
db.First(&pack)
}
func main() {
var firstHotel, firstPackage interface{}
//first method
firstHotel = GetFirstHotel()
firstPackage = GetFirstPackage()
//method i want to use
firstHotel = GetFirstItem(Hotel{})
firstPackage = GetFirstItem(Package{})
}
func GetFirstItem(item interface{}) interface{} {
//how to implement this?
//probably with some use of reflect package
}
The db.First method returns db reference and hydrates the row into the passed structure.
The closest to your desired method is
func GetFirstItem(item interface{}) error {
return db.First(item).Error
}
This simply requires you keep a reference to the parameter
var firstHotel &Hotel{}
err := GetFirstItem(firstHotel)
Returning the hydrated object for all types would required type parameters (generics). I think you'll find the current situation is workable within limits.
see also: Why no generics in Go?

How I can write a single function to work with different types

Given the following example, is it anyhow possible to create a function that can literally reproduce (not only get the reflect.Type) the actual type for further manipulation? I know go is statically typed and although it's very cool that I can pass any struct to a function that defines an interface parameter, is there any chance I can do more the other way around?
I already looked into the reflect package but only found stuff that returned a reflect.Type or reflect.Value. I used the New() method which returned a new reflect.Value - and there I couldn't set any fields. Maybe someone experienced with the reflect package can tell me if this is definitely possible or not - or if there's another way to do it.
package main
import "fmt"
type User struct {
Name string
}
func main() {
user := User{Name:"FooBar"}
DoSomethingGenericWithStruct(user)
}
func DoSomethingGenericWithStruct(i interface{}) {
// access fields of i ...
// or create slice of type of i ([]User) ...
// or instantiate new object of type of i (new User) ...
// ...
}
You would have to pass a pointer to your struct to be able to modify it.
Also keep in mind that using reflection has a high runtime performance cost.
func DoSomethingGenericWithStruct(i interface{}) {
val := reflect.ValueOf(i)
if val.Kind() != reflect.Ptr {
panic("need a pointer")
}
val = val.Elem() // now you can modify it
// add error checking and such, this will panic if it's not a struct or there's no "Name" field
val.FieldByName("Name").SetString("stuff")
}
playground
To create a new element and assign it:
val = val.Elem()
nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
nval.FieldByName("Name").SetString("stuff")
val.Set(nval)
to modify the actual struct, not reflect.Value, you will have to get the interface{} to it then assert it to your type, for example:
nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
user := nval.Interface().(User)
user.Name = "Stuff"
val.Set(reflect.ValueOf(user))

Resources