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}
Related
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()
}
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
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).
In functional programming likes Haskell, I can define function
add a b = a+b
Then add 3 will return a function that take one parameter and will return 3 + something
How can I do this in GO?
When I define a function that take more than one (say n) parameters, can I only give it one parameter and get another function that take n-1 parameters?
Update:
Sorry for the imprecise words in my original question.
I think my question should be asked as two qeustions:
Is there partial application in GO?
How GO do function curry?
Thanks TheOnly92 and Alex for solving my second question. However, I am also curious about the first question.
To extend on the previous answer, which allows you to take an arbitrary number of arguments:
package main
import (
"fmt"
)
func mkAdd(a int) func(...int) int {
return func(b... int) int {
for _, i := range b {
a += i
}
return a
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5,3), add3(6))
}
Perhaps something like
package main
import (
"fmt"
)
func mkAdd(a int) func(int) int {
return func(b int) int {
return a + b
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5), add3(6))
}
You can take it a step further by defining a function type and then adding a method to it.
package main
import "fmt"
type Add func(int, int) int
func (f Add) Apply(i int) func(int) int {
return func(j int) int {
return f(i, j)
}
}
func main() {
var add Add = func(i, j int) int { return i + j }
add3 := add.Apply(3)
fmt.Println("add 3 to 2:", add3(2))
}
You can even try with variadic functions:
package main
import "fmt"
type Multiply func(...int) int
func (f Multiply) Apply(i int) func(...int) int {
return func(values ...int) int {
values = append([]int{i}, values...)
return f(values...)
}
}
func main() {
var multiply Multiply = func(values ...int) int {
var total int = 1
for _, value := range values {
total *= value
}
return total
}
var times2 Multiply = multiply.Apply(2)
fmt.Println("times 2:", times2(3, 4), "(expect 24)")
// ... and you can even cascade (if assigned the Multiply type)
times6 := times2.Apply(3)
fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
}
Hope this helps!
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!