Get name of struct field using reflection - go

What is the way of printing "Foo" here? In this example, what prints is "string".
http://play.golang.org/p/ZnK6PRwEPp
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
val := reflect.Indirect(reflect.ValueOf(a))
fmt.Println(val.Field(0).Type().Name())
}

You want val.Type().Field(0).Name. The Field method on reflect.Type will return a struct describing that field, which includes the name, among other information.
There is no way to retrieve the field name for a reflect.Value representing a particular field value, since that is a property of the containing struct.

I think the better way to get the fields' name in the struct is
func main() {
a := &A{Foo: "afoo"}
val := reflect.ValueOf(a).Elem()
for i:=0; i<val.NumField();i++{
fmt.Println(val.Type().Field(i).Name)
}
}
There are two tips:
use .Elem() after you reflect.ValueOf(a), because in your case, a is a pointer.
val.Field(i).Type().Name is totally different from val.Type().Field(i).Name. The latter one can get the name of the field in the struct
Hope that it is helpful..
If you want to have a look at more cases, please check my 2mins article

You need to Get the Field of the Type Definition not of the Value.
http://play.golang.org/p/7Bc7MJikbJ
package main
import "fmt"
import "reflect"
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
val := reflect.Indirect(reflect.ValueOf(a))
fmt.Println(val.Type().Field(0).Name)
}

With the new Names method of the structs package it's even more easier:
package main
import (
"fmt"
"github.com/fatih/structs"
)
type A struct {
Foo string
Bar int
}
func main() {
names := structs.Names(&A{})
fmt.Println(names) // ["Foo", "Bar"]
}

You can also use https://github.com/fatih/structs
// Convert the fields of a struct to a []*Field
fields := s.Fields()
for _, f := range fields {
fmt.Printf("field name: %+v\n", f.Name())
}

package main
import "fmt"
import "reflect"
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
//long and bored code
t := reflect.TypeOf(*a)
if t.Kind() == reflect.Struct {
for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Name)
}
} else {
fmt.Println("not a stuct")
}
//shorthanded call
fmt.Println(reflect.TypeOf(*a).Field(0).Name)//can panic if no field exists
}

You can use this function, which takes the struct as the first parameter, and then its fields. It returns the map type, which is convenient to use
If you use fields from another structure, nothing will happen
If you try to use a different type, it will cause panic
Note that the field has an ordinal number according to the list (starting from 0). All fields in the structure must start with uppercase
func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {
fields = make(map[int]string)
s := reflect.ValueOf(Struct).Elem()
for r := range StructField {
f := reflect.ValueOf(StructField[r]).Elem()
for i := 0; i < s.NumField(); i++ {
valueField := s.Field(i)
if valueField.Addr().Interface() == f.Addr().Interface() {
fields[i] = s.Type().Field(i).Name
}
}
}
return fields
}
Full example and playground
package main
import (
"fmt"
"reflect"
)
type Example struct {
Apple bool
Pear int
}
func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {
fields = make(map[int]string)
for r := range StructField {
s := reflect.ValueOf(Struct).Elem()
f := reflect.ValueOf(StructField[r]).Elem()
for i := 0; i < s.NumField(); i++ {
valueField := s.Field(i)
if valueField.Addr().Interface() == f.Addr().Interface() {
fields[i] = s.Type().Field(i).Name
}
}
}
return fields
}
func main() {
e := Example{}
names := GetStructFieldName(&e, &e.Apple, &e.Pear)
fmt.Println(names)
fmt.Println(names[0], names[1])
for i := range names {
fmt.Println(names[i])
}
/* Output:
map[0:Apple 1:Pear]
Apple Pear
Apple
Pear
*/
}

Related

Using reflect to assign a typed value

I'm working on one of our system applications, specifically in the configuration file handling bits. We currently have 3 different places where a configuration file can be stored, and that can possibly be extended later. What I'm trying to do is simplify the way we need to add a new managed field.
The solution I have so far looks something like this:
package main
import (
"reflect"
"strconv"
"strings"
)
type Datastore interface{}
type MyInt struct {
intVal int
}
func NewMyInt(key string, dv int, db *Datastore) *MyInt {
// Do something here to construct MyInt
return &MyInt{intVal: dv}
}
type Config struct {
myInts map[string]*MyInt
// Tag is of form "<key in DB>:<default value>"
Value1 MyInt "value1_key:12345"
Value2 MyInt "value2_key:54321"
}
func NewConfig(db *Datastore) *Config {
c := &Config{
myInts: make(map[string]*MyInt),
}
cType := reflect.TypeOf(c)
for i := 0; i < cType.NumField(); i++ {
f := cType.Field(i)
if f.Name == "myInts" {
continue
}
tag := string(f.Tag)
fields := strings.Split(tag, ":")
switch f.Type.Name() {
case "myInt":
intVal, _ := strconv.Atoi(fields[1])
val := NewMyInt(fields[0], intVal, db)
c.myInts[fields[0]] = val
// How do I set the i'th field to this newly constructed value?
}
}
return c
}
So far I'm just missing this piece to do the assignment.
For this question, you can try
func NewConfig(db *Datastore) *Config {
c := &Config{
myInts: make(map[string]*MyInt),
}
cType := reflect.TypeOf(c).Elem() // have to use Elem() to get actual value
cValue := reflect.ValueOf(c).Elem()
for i := 0; i < cType.NumField(); i++ {
f := cType.Field(i)
if f.Name == "myInts" {
continue
}
tag := string(f.Tag)
fields := strings.Split(tag, ":")
switch f.Type.Name() {
case "MyInt":
intVal, _ := strconv.Atoi(fields[1])
val := NewMyInt(fields[0], intVal, db)
c.myInts[fields[0]] = val
// How do I set the i'th field to this newly constructed value?
cValue.Field(i).Set(reflect.ValueOf(val).Elem())
}
}
fmt.Println(c.Value1.intVal, c.Value2.intVal)
return c
}

In go (golang), how can you cast an interface pointer into a struct pointer?

I want to use some external code that requires a pointer to a struct. At the point that the code is called, I have an interface variable.
When creating a pointer off of that variable, the pointer's type is interface{}* when I need it to be the pointer type of the struct's type.
Image the code in TestCanGetStructPointer does not know about the Cat class, and that it exists in some external package.
How can I cast it to this?
Here is a code sample:
import (
"reflect"
"testing"
)
type Cat struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{}
}
var somethingForCats = SomethingGeneric{getSomething: getSomeCat}
func TestCanGetStructPointer(t *testing.T) {
interfaceVariable := somethingForCats.getSomething()
pointer := &interfaceVariable
interfaceVarType := reflect.TypeOf(interfaceVariable)
structPointerType := reflect.PtrTo(interfaceVarType)
pointerType := reflect.TypeOf(pointer)
if pointerType != structPointerType {
t.Errorf("Pointer type was %v but expected %v", pointerType, structPointerType)
}
}
The test fails with:
Pointer type was *interface {} but expected *parameterized.Cat
#dyoo's example does work, but it relies on you to manually cast Dog and Cat.
Here's a bit of a convoluted/verbose example which avoids that constraint somewhat:
package main
import (
"fmt"
"reflect"
)
type Cat struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{name: "Fuzzy Wuzzy"}
}
var somethingForCats = SomethingGeneric{getSomething: getSomeCat}
func main() {
interfaceVariable := somethingForCats.getSomething()
castVar := reflect.ValueOf(interfaceVariable)
castVar.Convert(castVar.Type())
// If you want a pointer, do this:
fmt.Println(reflect.PtrTo(castVar.Type()))
// The deref'd val
if castVar.Type() != reflect.TypeOf(Cat{}) {
fmt.Printf("Type was %v but expected %v\n", castVar, reflect.TypeOf(&Cat{}))
} else {
fmt.Println(castVar.Field(0))
}
}
Playground Link
I found this thread: https://groups.google.com/forum/#!topic/golang-nuts/KB3_Yj3Ny4c
package main
import (
"fmt"
"reflect"
)
type Cat struct {
name string
}
//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {
fmt.Println("obj is a", reflect.TypeOf(obj).Name())
// Create a new instance of the underlying type
vp := reflect.New(reflect.TypeOf(obj))
// Should be a *Cat and Cat respectively
fmt.Println("vp is", vp.Type(), " to a ", vp.Elem().Type())
vp.Elem().Set(reflect.ValueOf(obj))
// NOTE: `vp.Elem().Set(reflect.ValueOf(&obj).Elem())` does not work
// Return a `Cat` pointer to obj -- i.e. &obj.(*Cat)
return vp.Interface()
}
//
// Dump out a pointer ...
//
func test_ptr(ptr interface{}) {
v := reflect.ValueOf(ptr)
fmt.Println("ptr is a", v.Type(), "to a", reflect.Indirect(v).Type())
}
func main() {
cat := Cat{name: "Fuzzy Wuzzy"}
// Reports "*main.Cat"
test_ptr(&cat)
// Get a "*Cat" generically via interface{}
sp := to_struct_ptr(cat)
// *should* report "*main.Cat" also
test_ptr(sp)
fmt.Println("sp is",sp)
}
The following may help: http://play.golang.org/p/XkdzeizPpP
package main
import (
"fmt"
)
type Cat struct {
name string
}
type Dog struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{name: "garfield"}
}
func getSomeDog() interface{} {
return Dog{name: "fido"}
}
var somethings = []SomethingGeneric{
SomethingGeneric{getSomething: getSomeCat},
SomethingGeneric{getSomething: getSomeDog},
}
func main() {
for _, something := range somethings {
interfaceVariable := something.getSomething()
cat, isCat := interfaceVariable.(Cat)
dog, isDog := interfaceVariable.(Dog)
fmt.Printf("cat %v %v\n", cat, isCat)
fmt.Printf("dog %v %v\n", dog, isDog)
}
}

unexported field or method for go interface

I am quite new to go, and I am trying to loop through each field of an interface (can be different struct) but I am not sure what is going wrong with the following code? it reports runtime error: panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
what are those unexported field/method? I have the SomeField field capitalized thanks
type SomeStruct struct {
SomeField uint32
}
func test(obj interface{}){
typ := reflect.TypeOf(obj)
val := reflect.ValueOf(obj)
for i := 0; i < typ.NumField(); i++ {
fieldValue := val.Field(i).Interface()
fmt.Println(fieldValue)
}
}
func test1(obj interface{}){
val := reflect.ValueOf(obj)
test(val)
}
func main() {
var ss SomeStruct
test1(ss)
}
in Go struct,field started in lowercase means its scope is private,while uppercase means public. So,you should keep the field started with UpperCase alpha.
I think you just wanted to run this:
package main
import "fmt"
import "reflect"
type SomeStruct struct {
SomeField uint32
}
func test(obj interface{}){
typ := reflect.TypeOf(obj)
val := reflect.ValueOf(obj)
for i := 0; i < typ.NumField(); i++ {
fieldValue := val.Field(i).Interface()
fmt.Println(fieldValue)
}
}
func main() {
var ss SomeStruct
test(ss)
ss.SomeField = 1
test(ss)
}
Your original code tries to get a value of each field of val := reflect.ValueOf(ss) instead of ss.

Iterate through the fields of a struct in Go

Basically, the only way (that I know of) to iterate through the values of the fields of a struct is like this:
type Example struct {
a_number uint32
a_string string
}
//...
r := &Example{(2 << 31) - 1, "...."}:
for _, d:= range []interface{}{ r.a_number, r.a_string, } {
//do something with the d
}
I was wondering, if there's a better and more versatile way of achieving []interface{}{ r.a_number, r.a_string, }, so I don't need to list each parameter individually, or alternatively, is there a better way to loop through a struct?
I tried to look through the reflect package, but I hit a wall, because I'm not sure what to do once I retrieve reflect.ValueOf(*r).Field(0).
Thanks!
After you've retrieved the reflect.Value of the field by using Field(i) you can get a
interface value from it by calling Interface(). Said interface value then represents the
value of the field.
There is no function to convert the value of the field to a concrete type as there are,
as you may know, no generics in go. Thus, there is no function with the signature GetValue() T
with T being the type of that field (which changes of course, depending on the field).
The closest you can achieve in go is GetValue() interface{} and this is exactly what reflect.Value.Interface()
offers.
The following code illustrates how to get the values of each exported field in a struct
using reflection (play):
import (
"fmt"
"reflect"
)
func main() {
x := struct{Foo string; Bar int }{"foo", 2}
v := reflect.ValueOf(x)
values := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
values[i] = v.Field(i).Interface()
}
fmt.Println(values)
}
If you want to Iterate through the Fields and Values of a struct then you can use the below Go code as a reference.
package main
import (
"fmt"
"reflect"
)
type Student struct {
Fname string
Lname string
City string
Mobile int64
}
func main() {
s := Student{"Chetan", "Kumar", "Bangalore", 7777777777}
v := reflect.ValueOf(s)
typeOfS := v.Type()
for i := 0; i< v.NumField(); i++ {
fmt.Printf("Field: %s\tValue: %v\n", typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
Run in playground
Note: If the Fields in your struct are not exported then the v.Field(i).Interface() will give panic panic: reflect.Value.Interface: cannot return value obtained from unexported field or method.
Go 1.17 (Q3 2021) should add a new option, through commit 009bfea and CL 281233, fixing issue 42782.
reflect: add VisibleFields function
When writing code that reflects over a struct type, it's a common requirement to know the full set of struct fields, including fields available due to embedding of anonymous members while excluding fields that are erased because they're at the same level as another field with the same name.
The logic to do this is not that complex, but it's a little subtle and easy to get wrong.
This CL adds a new reflect.VisibleFields() function to the reflect package that returns the full set of effective fields that apply in a given struct type.
fields := reflect.VisibleFields(typ)
for j, field := range fields {
...
}
Example,
type employeeDetails struct {
id int16
name string
designation string
}
func structIterator() {
fields := reflect.VisibleFields(reflect.TypeOf(struct{ employeeDetails }{}))
for _, field := range fields {
fmt.Printf("Key: %s\tType: %s\n", field.Name, field.Type)
}
}
Maybe too late :))) but there is another solution that you can find the key and value of structs and iterate over that
package main
import (
"fmt"
"reflect"
)
type person struct {
firsName string
lastName string
iceCream []string
}
func main() {
u := struct {
myMap map[int]int
mySlice []string
myPerson person
}{
myMap: map[int]int{1: 10, 2: 20},
mySlice: []string{"red", "green"},
myPerson: person{
firsName: "Esmaeil",
lastName: "Abedi",
iceCream: []string{"Vanilla", "chocolate"},
},
}
v := reflect.ValueOf(u)
for i := 0; i < v.NumField(); i++ {
fmt.Println(v.Type().Field(i).Name)
fmt.Println("\t", v.Field(i))
}
}
and there is no *panic* for v.Field(i)
use this:
type x struct {
Id int
jsj int
}
func main() {
x2 := x{jsj: 10, Id: 5}
v := reflect.ValueOf(x2)
for i := 0; i < v.NumField(); i++ {
fmt.Println(v.Field(i))
}
}
====>10
====>5
Taking Chetan Kumar solution and in case you need to apply to a map[string]int
package main
import (
"fmt"
"reflect"
)
type BaseStats struct {
Hp int
HpMax int
Mp int
MpMax int
Strength int
Speed int
Intelligence int
}
type Stats struct {
Base map[string]int
Modifiers []string
}
func StatsCreate(stats BaseStats) Stats {
s := Stats{
Base: make(map[string]int),
}
//Iterate through the fields of a struct
v := reflect.ValueOf(stats)
typeOfS := v.Type()
for i := 0; i< v.NumField(); i++ {
val := v.Field(i).Interface().(int)
s.Base[typeOfS.Field(i).Name] = val
}
return s
}
func (s Stats) GetBaseStat(id string) int {
return s.Base[id]
}
func main() {
m := StatsCreate(BaseStats{300, 300, 300, 300, 10, 10, 10})
fmt.Println(m.GetBaseStat("Hp"))
}
Use reflect package. First, get the type of variable with reflect.TypeOf and get numbers of elements with reflect.NumField.To obtain the values of the fields iteratively of a structure must reflect the variable and use the function rg.Elem().Field(i)
package main
import (
"fmt"
"reflect"
)
type Gopher struct {
Name string
Color string
Year int
}
func main() {
g := Gopher{Name: "AAA", Color: "BBBB", Year: 2021}
gtype := reflect.TypeOf(g)
numFields := gtype.NumField()
rg := reflect.ValueOf(&g)
for i := 0; i < numFields; i++ {
fmt.Println(rg.Elem().Field(i))
}
}
In Go, you can use the reflect package to iterate through the fields of a struct. The reflect package allows you to inspect the properties of values at runtime, including their type and value. Here's an example of how to iterate through the fields of a struct:
Go Playground
package main
import (
"fmt"
"reflect"
)
type Movie struct {
Name string
Year int
}
func main() {
p := Movie{"The Dark Knight", 2008}
val := reflect.ValueOf(p)
typ := val.Type()
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldType := typ.Field(i)
fmt.Printf("Field Name: %s, Field Value: %v\n", fieldType.Name, field.Interface())
}
}
Output:
Field Name: Name, Field Value: The Dark Knight
Field Name: Age, Field Value: 2008

How do I access struct fields that are part of a vector.Vector?

I am looking for help understanding how to access struct fields that are inside a container.vector.Vector.
The following code:
package main
import "fmt"
import "container/vector"
func main() {
type Hdr struct {
H string
}
type Blk struct {
B string
}
a := new(vector.Vector)
a.Push(Hdr{"Header_1"})
a.Push(Blk{"Block_1"})
for i := 0; i < a.Len(); i++ {
fmt.Printf("a.At(%d) == %+v\n", i, a.At(i))
x := a.At(i)
fmt.Printf("%+v\n", x.H)
}
}
Produces the error prog.go:22: x.H undefined (type interface { } has no field or method H)
removing lines 21 and 22 produces:
a.At(0) == {H:Header_1}
a.At(1) == {B:Block_1}
So, how exactly does one access 'H' or 'B'? It seems like I need to convert those interfaces to structs, but... I dunno. I'm at a loss.
Thanks for any help.
Use a Go type switch or type assertion to distinguish between the Hdr and Blk types. For example,
package main
import (
"fmt"
"container/vector"
)
func main() {
type Hdr struct {
H string
}
type Blk struct {
B string
}
a := new(vector.Vector)
a.Push(Hdr{"Header_1"})
a.Push(Blk{"Block_1"})
for i := 0; i < a.Len(); i++ {
fmt.Printf("a.At(%d) == %+v\n", i, a.At(i))
x := a.At(i)
switch x := x.(type) {
case Hdr:
fmt.Printf("%+v\n", x.H)
case Blk:
fmt.Printf("%+v\n", x.B)
}
}
}
However, effective the weekly.2011-10-18 release:
The container/vector package has been deleted. Slices are better:
SliceTricks.
Therefore, for the latest releases,
package main
import "fmt"
func main() {
type Hdr struct {
H string
}
type Blk struct {
B string
}
var a []interface{}
a = append(a, Hdr{"Header_1"})
a = append(a, Blk{"Block_1"})
for i := 0; i < len(a); i++ {
fmt.Printf("a[%d]) == %+v\n", i, a[i])
x := a[i]
switch x := x.(type) {
case Hdr:
fmt.Printf("%+v\n", x.H)
case Blk:
fmt.Printf("%+v\n", x.B)
}
}
}

Resources