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)
}