Go, %v format invoking String() for a nested struct - go

In the following code, I would expect fmt.Printf("%v\n", a) to invoke String() of its member of type myTypeB, but this is not happening ? Why ?
package main
import "fmt"
type myTypeA struct {
b myTypeB
}
type myTypeB struct {
c string
d int
}
func (b myTypeB) String() string {
return "myTypeB custom"
}
func main() {
a:= myTypeA{myTypeB{"hello", 1}};
b:= myTypeB{"hello", 1}
fmt.Printf("%v\n", a)
fmt.Printf("%v\n", b)
}
Playground link

fmt doesn't look for fmt.Stringer recursively.
If the argument is a fmt.Stringer, it will invoke the String() method, and print the results. If it doesn't have a String() method, fmt will iterate over the fields using reflection to obtain the value.

Related

Chainable struct methods that satisfies multiple interfaces?

I have a need to create multiple structs with almost the same fields and methods with the same actions. Instead of doing that I thought, why not create a single struct and use interfaces to limit interactions. It worked great! Now the problem. I want the methods to be chainable. To do that, methods need to return a reference to the struct. After doing that, all the returns complain that (struct) does not implement <interface> (wrong type for <method> method). Which is expected.
The question is, is it possible to use a single struct with multiple interfaces that has chainable methods? Or is creating individual, duplicate, structs for every interface the only way?
I thought of using composition but I still need to define methods that will call the embedded struct methods, in which case there's no difference to creating new pure structs.
Example problem:
https://play.golang.org/p/JrsHATdi2dr
package main
import (
"fmt"
)
type A interface {
SetA(string) A
Done()
}
type B interface {
SetB(string) B
Done()
}
type t struct {
a string
b string
}
func (t *t) SetA(a string) *t { t.a = a; return t }
func (t *t) SetB(b string) *t { t.b = b; return t }
func (t *t) Done() { fmt.Println(t.a, t.b) }
func NewTA() A {
return &t{}
}
func NewTB() B {
return &t{}
}
func main() {
fmt.Println("Hello, playground")
ta := NewTA()
ta.SetA("a")
ta.Done()
tb := NewTB()
tb.SetB("b")
tb.Done()
}
When you use *t as return type in SetA and SetB that means t are not implement A and B interface. The signature of SetA and SetB function of *t doesn't match with interface A and B accordingly.
Accually SetA(a string) A and SetA(a string) *t are not same think. You used A as return type for SetA in interface but use *t as return type for t, go doesn't support this. Same for SetB function
If you do like this then it will work because now function signature matched
func (t *t) SetA(a string) A { t.a = a; return A(t) }
func (t *t) SetB(b string) B { t.b = b; return B(t) }
Code in go playground here

Why my Golang defined method not implemented implicitily while String() does

In https://tour.golang.org/methods/11
It states Under the hood, interface values can be thought of as a tuple of a value and a concrete type
I define M as follows
script1
package main
import (
"fmt"
)
type I interface {
M() string
}
type T struct {
S string
w string
}
func (t T) M() string {
return "dddd"
}
func main() {
var i I
i = T{"Hello","eeee"}
fmt.Printf("(%v, %T)", i, i)
fmt.Println(i)
}
This prints out ({Hello eee}, main.T){Hello eee}
interface i has vaule {Hello eee} and type main.T
script2:
package main
import (
"fmt"
)
type I interface {
M() string
}
type T struct {
S string
w string
}
func (t T) M() string {
return "dddd"
}
func (t T) String() string {
return "ccccc"
}
func main() {
var i I
i = T{"Hello","eeee"}
fmt.Printf("(%v, %T)", i, i)
fmt.Println(i)
}
This prints out (ccccc, main.T)ccccc.
interface i has vaule ccccc and type main.T
Seems when i add String() as Stringer defined by the fmt package in script2. The String() is implemented implicitily,not sure why?
I thought in script2 i would have value "{Hello eee}" and type main.T
You should call fmt.Println(i.M()) ?
Why you want fmt call a function while its'n exist?
A Stringer is a type that can describe itself as a string. The fmt package (and many others) look for this interface to print values
Refer: https://golang.org/pkg/fmt/#Stringer
Stringer is implemented by any value that has a String method, which
defines the “native” format for that value. The String method is used
to print values passed as an operand to any format that accepts a
string or to an unformatted printer such as Print.
In your case, in script1 you are just printing out the struct. In script2 you are providing what the builder should use when an unformatted print occurs which is a function that prints out "ccccc".

Why %v is printing unexpected value for nested struct?

When printing a struct with nested struct which has a String() implemented, the %v format prints an 'unexpected' value per our understanding.
Below is the code snippet.
package main
import (
"fmt"
)
type Inner struct {
}
type A struct {
Inner
FieldA string
}
func (i Inner) String() string {
return "anything"
}
func main() {
myA := A{FieldA: "A"}
fmt.Printf("%v", myA)
}
We expect the output to be
{anything A}
But the actual result is
anything
Why this result? It seems FieldA is ignored? To make it more confusing, if we have two nested structs where both of them have String() implemented, the output is expected.
package main
import (
"fmt"
)
type Inner struct {
}
type InnerAgain struct {
}
type A struct {
Inner
InnerAgain
FieldA string
}
func (i Inner) String() string {
return "anything"
}
func (i InnerAgain) String() string {
return "nothing"
}
func main() {
myA := A{FieldA: "A"}
fmt.Printf("%v", myA)
}
The output is
{anything nothing A}
...
Since you are embedding Inner, you inherent all its properties - including the String() - function. So %v is actually calling Inner.String()
From the docs (https://golang.org/pkg/fmt/) :
If an operand implements method String() string, that method will
be invoked to convert the object to a string, which will then be
formatted as required by the verb (if any).
Because the fmt package states the rules for %v as:
If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:
If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
Hence, %v actually uses the String() method for arguments that are stringers.

Make an arbitrary slice type stringer method in Go

New to Golang. So I read about the stringer in the Go tour and I'm wondering is there any way to define a generic custom Stringer() for any type of slice? E.g.:
package main
import "fmt"
type IntSlice []int
func (a IntSlice) String() string {
return fmt.Sprintf("len %d\tcap %d", len(a), cap(a))
}
func main() {
a:=[40]int{}
sa:=IntSlice(a[:])
fmt.Println(unsafe.Sizeof(a), "\t", unsafe.Sizeof(sa), " ", cap(sa))
fmt.Println(sa)
}
Like this but without the type IntSlice definition.
Thanks!
type SliceStringer struct {
Slice interface{}
}
func (ss SliceStringer) String() string {
rv := reflect.ValueOf(ss.Slice)
return fmt.Sprintf("len %d\tcap %d", rv.Len(), rv.Cap())
}
https://play.golang.org/p/jWnm9vCDFhq

Print all properties of struct even through that struct has a default string representation?

Normally, I can print all properties of an object with:
c.Infof("car: %+v", car)
But one struct has a String() method. I think that this causes the line above to only print what the String() method returns.
How can I override this and force print all properties of that struct?
An easy workaround is to use the %#v verb:
package main
import (
"fmt"
)
type someStruct struct {
a int
b int
}
func (someStruct) String() string {
return "this is the end"
}
func main() {
fmt.Printf("%+v\n", someStruct{1, 2})
fmt.Printf("%#v\n", someStruct{1, 2})
}
This prints:
this is the end
main.someStruct{a:1, b:2}

Resources