Description
While wrong, for convinience sometimes we use interfaces to pass around values of certain types.
An example for this would be the following:
package main
type S interface{}
package main() {
var s S
s = "someString"
}
From the golang tutorial we know that if we want to cast (assert) the value of an interface back to the original type, we use
interfaceVar.(type)
For the example from above if we wanted to pass “someString” back to a string variable, we would do it like this
var someString string
someString = s.(string)
The above works for any type that is visible in the package that is running the above casting. But how do we export the fields of a struct if the strcut’s type is not visible in the package that is trying to do the assertion?
Take this as an example
// Some different package
package utils
type utils struct {
Name string
}
func NewFactory(n string) interface{} {
return &utils{
Name: n,
}
}
// Package main
package main
import (
"fmt"
"myproject/utils"
)
func main() {
v := utils.NewFactory("test")
fmt.Println(v)
}
If we try to get the v.Name value we will get an error ./main.go:33:15: v.Name undefined (type interface {} is interface with no methods), also we can not cast v.(utils) since utils is a private struct (not exported).
A workaround for this issue is to use the reflect package
Soluton
To get the field use “reflect” package as demonstrated below
package main
import (
"fmt"
"reflect"
"myproject/utils"
)
func main() {
v := NewFactory("test")
k := reflect.ValueOf(v).Elem()
var s string
s = k.FieldByName("Name").Interface().(string)
fmt.Println(s)
}