How to implement GetStringValueByField(n interface{}, field_name string) string - reflection

I am trying to implement a method to get a value from a arbitrary struct-field as a string given by the struct and the fieldname as a string.
With reflect it is always panicing.
panic: reflect: call of reflect.Value.FieldByName on interface Value
goroutine 16 [running]
// attempt to implement GetStringValueByFieldName()
package main
import "fmt"
import "reflect"
import "strconv"
func main() {
a:=Order{A:"asdf", B:123}
fmt.Println(a)
fmt.Println(Test1(a, "A"))
fmt.Println(Test1(a, "B"))
}
type Order struct {
A string
B int64
}
func Test1 (n interface{}, field_name string) string {
var x string
s := reflect.ValueOf(&n).Elem()
x, ok := s.FieldByName(field_name).Interface().(string)
if ok {
fmt.Println(ok)
}
return x
}
func GetStringValueByFieldName(n interface{}, field_name string) string {
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
f := s.FieldByName(field_name)
if f.IsValid() {
if f.CanSet() {
if f.Kind() == reflect.Int {
return strconv.FormatInt(f.Int(),10)
}
if f.Kind() == reflect.String {
return f.String()
}
}
}
}
return ""
}

Here's how to get a string field by name:
package main
import (
"fmt"
"reflect"
)
func main() {
a := Order{A: "asdf", B: 123}
fmt.Println(a)
fmt.Println(GetStringValueByFieldName(a, "A"))
fmt.Println(GetStringValueByFieldName(&a, "A"))
fmt.Println(GetStringValueByFieldName(a, "B"))
fmt.Println(GetStringValueByFieldName(0, "B"))
fmt.Println(GetStringValueByFieldName(a, "C"))
}
type Order struct {
A string
B int64
}
func GetStringValueByFieldName(n interface{}, field_name string) (string, bool) {
s := reflect.ValueOf(n)
if s.Kind() == reflect.Ptr {
s = s.Elem()
}
if s.Kind() != reflect.Struct {
return "", false
}
f := s.FieldByName(field_name)
if !f.IsValid() {
return "", false
}
switch f.Kind() {
case reflect.String:
return f.Interface().(string), true
case reflect.Int:
return strconv.FormatInt(f.Int(), 10), true
// add cases for more kinds as needed.
default:
return "", false
// or use fmt.Sprint(f.Interface())
}
}
playground

Related

golang how to print struct value with pointer

package main
import "fmt"
type A struct {
a int32
B *B
}
type B struct {
b int32
}
func main() {
a := &A{
a: 1,
B: &B{
b: 2,
},
}
fmt.Printf("v ==== %+v \n", a)
}
//ret: v ==== &{a:1 B:0xc42000e204}
//??? how to print B's content but not pointer
Basically, you have to do it yourself. There are two ways to do this. Either just print the thing how you want, or implement the Stringer interface for the struct by adding a func String() string, which gets called when you use the format %v. You could also reference each value in the format which is a struct.
Implementing the Stringer interface is the surest way to always get what you want. And you only have to do it once per struct, instead of per format string when you print.
https://play.golang.org/p/PKLcPFCqOe
package main
import "fmt"
type A struct {
a int32
B *B
}
type B struct{ b int32 }
func (aa *A) String() string {
return fmt.Sprintf("A{a:%d, B:%v}",aa.a,aa.B)
}
func (bb *B) String() string {
return fmt.Sprintf("B{b:%d}",bb.b)
}
func main() {
a := &A{a: 1, B: &B{b: 2}}
// using the Stringer interface
fmt.Printf("v ==== %v \n", a)
// or just print it yourself however you want.
fmt.Printf("v ==== A{a:%d, B:B{b:%d}}\n", a.a, a.B.b)
// or just reference the values in the struct that are structs themselves
// but this can get really deep
fmt.Printf("v ==== A{a:%d, B:%v}", a.a, a.B)
}
When you get into larger structs, it becomes a pain to write a bunch of custom String functions. Goconvey currently uses the following project to show diffs and expected/actual output on structs of any size: https://github.com/luci/go-render/blob/master/render/render.go#L51. It includes displaying pointer values.
If you need the output to be re-usable as code (like fmt.Printf("%#v", a) but include pointer values), I have a forked version of the above project which will render full nested pointers as re-usable code:
package main
import (
"fmt"
"github.com/gdexlab/go-render/render"
)
type A struct {
a int32
B *B
}
type B struct {
b int32
}
func main() {
a := &A{
a: 1,
B: &B{
b: 2,
},
}
output := render.AsCode(a)
fmt.Println(output)
}
// outputs: "&A{a:1, B:&B{b:2}}" compared to initial version of "&{a:1 B:0xc42000e204}"
Go Playground Example:
https://play.golang.org/p/tcfJYb0NnVf
Another simple solution is to print the struct using marshaling. This works only for exported (public) variables by capitalizing the first char inside the struct.
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"encoding/json"
)
type A struct {
Aa int32
B *B
}
type B struct {
Bb int32
}
func main() {
a := &A{
Aa: 1,
B: &B{
Bb: 2,
},
}
aJSON, _ := json.Marshal(a)
fmt.Printf("JSON Print - \n%s\n", string(aJSON))
aYAML, _ := yaml.Marshal(a)
fmt.Printf("YAML Print - \n%s\n", string(aYAML))
}
Output :-
JSON Print -
{"Aa":1,"B":{"Bb":2}}
YAML Print -
aa: 1
b:
bb: 2
If you are printing the struct multiple times then implement Stringer interface as follows :-
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type A struct {
Aa int32
B *B
}
func (a A) String() string {
bytes, _ := yaml.Marshal(a)
return string(bytes)
}
type B struct {
Bb int32
}
func main() {
a := &A{
Aa: 1,
B: &B{
Bb: 2,
},
}
fmt.Printf("YAML Print - \n%+v\n", a)
}
Output -
YAML Print -
aa: 1
b:
bb: 2
Use fmt and reflect.
package main
import (
"fmt"
"reflect"
)
type A struct {
a int32
B *B
}
type B struct {
b int32
}
func main() {
a := &A{
a: 1,
B: &B{
b: 2,
},
}
fmt.Printf("%s\n", GetGoString(a)) // output: &A{a: 1, B: &B{b: 2}}
}
func GetGoString(v interface{}) string {
return getGoString(reflect.ValueOf(v))
}
func getGoString(v reflect.Value) string {
switch v.Kind() {
case reflect.Invalid:
return "nil"
case reflect.Struct:
t := v.Type()
out := getTypeString(t) + "{"
for i := 0; i < v.NumField(); i++ {
if i > 0 {
out += ", "
}
fieldValue := v.Field(i)
field := t.Field(i)
out += fmt.Sprintf("%s: %s", field.Name, getGoString(fieldValue))
}
out += "}"
return out
case reflect.Interface, reflect.Ptr:
if v.IsZero() {
return fmt.Sprintf("(%s)(nil)", getTypeString(v.Type()))
}
return "&" + getGoString(v.Elem())
case reflect.Slice:
out := getTypeString(v.Type())
if v.IsZero() {
out += "(nil)"
} else {
out += "{"
for i := 0; i < v.Len(); i++ {
if i > 0 {
out += ", "
}
out += getGoString(v.Index(i))
}
out += "}"
}
return out
default:
return fmt.Sprintf("%#v", v)
}
}
func getTypeString(t reflect.Type) string {
if t.PkgPath() == "main" {
return t.Name()
}
return t.String()
}
Implement Stringer interface to custom type
no external packages
no need to wrap types in other types
example:
package main
import "fmt"
type A struct {
B *B `json:"b"`
}
type B int
func (b *B) String() string {
if b == nil {
return "nil"
}
return fmt.Sprintf("%d", *b)
}
func main() {
var a A
fmt.Printf("a: %+v\n", a)
a.B = B(3)
fmt.Printf("a: %+v\n", a)
}
output:
a: {B:nil}
a: {B:3}

Golang: Function to determine the arity of functions?

Is it possible to write a function to determine the arity of arbitrary functions, such that:
1.
func mult_by_2(x int) int {
return 2 * x
}
fmt.Println(arity(mult_by_2)) //Prints 1
2.
func add(x int, y int) int {
return x + y
}
fmt.Println(arity(add)) //Prints 2
3.
func add_3_ints(a, b, c int) int {
return b + a + c
}
fmt.Println(arity(add_3_ints)) //Prints 3
You can write such a function using the reflect package:
import (
"reflect"
)
func arity(value interface{}) int {
ref := reflect.ValueOf(value)
tpye := ref.Type()
if tpye.Kind() != reflect.Func {
// You could define your own logic here
panic("value is not a function")
}
return tpye.NumIn()
}

Reflection type does not have method

I'm trying to use reflection in Go. Why doesn't this code list the methods? It lists the fields.
is this the problem? value interface{} I'm not sure how to pass a generic struct/class/type to a function. Normally I would just pass an Object.
(I'm totally new at this. I'm a C# programmer)
package main
import (
"fmt"
"reflect"
)
func main() {
var B TestType = TestType{TestString: "Hello", TestNumber: 3}
ListMethods(B)
}
func ListMethods(value interface{}) {
fooType := reflect.TypeOf(value)
for i := 0; i < fooType.NumMethod(); i++ {
method := fooType.Method(i)
fmt.Println("Method = " + method.Name)
}
for i := 0; i < fooType.NumField(); i++ {
field := fooType.Field(i)
fmt.Println("Field = " + field.Name)
fmt.Println(reflect.ValueOf(value).Field(i))
}
}
type TestType struct {
TestString string
TestNumber int
}
func (this *TestType) TestFunction() {
fmt.Println("Test")
}
Because you are passing a type and you declared a method to the pointer of the type.
https://play.golang.org/p/B0NdVyxGxt
Look at this example extended from yours:
package main
import (
"fmt"
"reflect"
)
func main() {
var B TestType = TestType{TestString: "Hello", TestNumber: 3}
ListMethods(B)
}
func ListMethods(value interface{}) {
fooType := reflect.TypeOf(value)
ptrFooType := reflect.PtrTo(fooType)
for i := 0; i < fooType.NumMethod(); i++ {
method := fooType.Method(i)
fmt.Println("Method = " + method.Name)
}
for i := 0; i < ptrFooType.NumMethod(); i++ {
method := ptrFooType.Method(i)
fmt.Println("* Method = " + method.Name)
}
for i := 0; i < fooType.NumField(); i++ {
field := fooType.Field(i)
fmt.Println("Field = " + field.Name)
fmt.Println(reflect.ValueOf(value).Field(i))
}
}
type TestType struct {
TestString string
TestNumber int
}
func (this *TestType) TestFunctionPtr() {
fmt.Println("Test")
}
func (this TestType) TestFunction() {
fmt.Println("Test Non Ptr")
}
Notice how the *Type can access also the Type Methods. But Type cannot access to *Type Methods.
To convert from Type to *Type I have used the reflect.PtrTo(Type).

How to convert type of map in golang

The function B return type map[T][]T like this:
type T interface{}
func B() map[T][]T {
result := make(map[T][]T)
return result
}
And now I have a function A call function B like this:
func A() map[string][]string {
res := B()
return res.(map[string][]string) //I'm sure the type is map[string][]string, so I use assertion, but it doesn't works
}
So, how can I do this cover type of map?
You can't. Those are completely different types.
You have to copy and type cast item by item: http://play.golang.org/p/uhLPytbhpR
import "fmt"
type T interface{}
func B() map[T][]T {
result := make(map[T][]T)
return result
}
func A() map[string][]string {
res := B()
result := make(map[string][]string)
for k,v := range res {
key := k.(string)
value := make([]string, 0, len(res))
for i := 0; i<len(value); i +=1 {
value[i] = v[i].(string)
}
result[key]= value
}
return result
}
func main() {
fmt.Println("Hello, playground", A())
}
A different approach is to return T not map[T][]Tplay:
type T interface{}
func B() T {
result := map[string][]string{
"test": {"test", "test"},
}
return T(result)
}
func A() map[string][]string {
res := B()
if v, ok := res.(map[string][]string); ok {
return v
}
return nil
}
func main() {
fmt.Println("Hello, playground", A())
}
// Edit, converter function : http://play.golang.org/p/cW_PNTqauV
func makeMap() map[T][]T {
return map[T][]T{
"test": {"test", "test"},
"stuff": {"stuff", 1212, "stuff"},
1: {10, 20},
}
}
func convertMap(in map[T][]T) (out map[string][]string) {
out = make(map[string][]string, len(in))
for k, _ := range in {
if ks, ok := k.(string); ok {
v := in[k] // this way we won't use a copy in the for loop
out[ks] = make([]string, 0, len(v))
for i := range v {
if vs, ok := v[i].(string); ok {
out[ks] = append(out[ks], vs)
} else {
fmt.Printf("Error: %v (%T) is not a string.\n", v[i], v[i])
}
}
} else {
fmt.Printf("Error: %v (%T) is not a string.\n", k, k)
}
}
return
}
func main() {
fmt.Println(convertMap(makeMap()))
}

How to cast reflect.Value to its type?

How to cast reflect.Value to its type?
type Cat struct {
Age int
}
cat := reflect.ValueOf(obj)
fmt.Println(cat.Type()) // Cat
fmt.Println(Cat(cat).Age) // doesn't compile
fmt.Println((cat.(Cat)).Age) // same
Thanks!
concreteCat,_ := reflect.ValueOf(cat).Interface().(Cat)
see http://golang.org/doc/articles/laws_of_reflection.html
fox example
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)
Ok, I found it
reflect.Value has a function Interface() that converts it to interface{}
This func auto-converts types as needed. It loads a config file values into a simple struct based on struct name and fields:
import (
"fmt"
toml "github.com/pelletier/go-toml"
"log"
"os"
"reflect"
)
func LoadConfig(configFileName string, configStruct interface{}) {
defer func() {
if r := recover(); r != nil {
fmt.Println("LoadConfig.Recovered: ", r)
}
}()
conf, err := toml.LoadFile(configFileName)
if err == nil {
v := reflect.ValueOf(configStruct)
typeOfS := v.Elem().Type()
sectionName := getTypeName(configStruct)
for i := 0; i < v.Elem().NumField(); i++ {
if v.Elem().Field(i).CanInterface() {
kName := conf.Get(sectionName + "." + typeOfS.Field(i).Name)
kValue := reflect.ValueOf(kName)
if (kValue.IsValid()) {
v.Elem().Field(i).Set(kValue.Convert(typeOfS.Field(i).Type))
}
}
}
} else {
fmt.Println("LoadConfig.Error: " + err.Error())
}
}
Seems the only way would be to do a switch statement similar to (code below) (also, something like the commented line would've-been nice though doesn't work (:()):
func valuesFromStruct (rawV interface{}) []interface{} {
v := reflect.ValueOf(rawV)
out := make([]interface{}, 0)
for i := 0; i < v.NumField(); i += 1 {
field := v.Field(i)
fieldType := field.Type()
// out = append(out, field.Interface().(reflect.PtrTo(fieldType)))
switch (fieldType.Name()) {
case "int64":
out = append(out, field.Interface().(int64))
break`enter code here`
case "float64":
out = append(out, field.Interface().(float64))
break
case "string":
out = append(out, field.Interface().(string))
break
// And all your other types (here) ...
default:
out = append(out, field.Interface())
break
}
}
return out
}
Cheers!

Resources