Should I check for nil values in the constructor and then set an unexported struct field, or make the default struct value useful by checking for nil at method level?
type Foo struct{}
func (f *Foo) Baz() {}
var DefaultFoo = new(Foo)
type Bar struct {
Foo *Foo
}
func (b *Bar) Baz() {
if b.Foo == nil {
DefaultFoo.Baz()
} else {
b.Foo.Baz()
}
}
or
type Foo struct{}
func (f *Foo) Baz() {}
var DefaultFoo = new(Foo)
type Bar struct {
foo *Foo
}
func NewBar(foo *Foo) *Bar {
if foo == nil {
foo = DefaultFoo
}
return &Bar{foo}
}
func (b *Bar) Baz() {
b.foo.Baz()
}
I don't think there is a "right" answer for this.
Having said this, the approach usually seen in the Go base libraries is letting the objects be created without any constructor, with nil or zero values in its fields, and then make the methods have logic to use or return useful defaults.
Take a look at the http.Client implementation for example:
https://github.com/golang/go/blob/master/src/net/http/client.go
It will basically let you create a new client by just doing:
client := &http.Client{}
You can then populate the fields of the object if you want to override defaults, otherwise it'll check for nil in different methods to provide default behaviour, for example:
https://github.com/golang/go/blob/master/src/net/http/client.go#L195
func (c *Client) transport() RoundTripper {
if c.Transport != nil {
return c.Transport
}
return DefaultTransport
}
Related
Imagine I have some types and an interface:
type Foo struct {}
type Bar struct {}
type Stuff interface {
IsStuff()
}
func (_ Foo) IsStuff() {}
func (_ Bar) IsStuff() {}
Now imagine I have a function that may return Stuff or nothing.
func FindStuff() ??? {
// ...
}
If the return type was a normal struct I could just return a pointer to the struct and return nil inside the function.
But using pointer to interfaces seems to be frowned upon in Go (and it's also tricky to find if the interface is nil).
So how to define FindStuff?
Just return the interface, it allows you to return nil:
func FindStuff() Stuff {
return nil
}
Working example
I have read several examples/questions about reflection in Go, but I'm still unable to understand what I'm supposed to do with my list of interfaces.
Below is a stripped down version of the real use case.
I have several types complying with a given interface:
type Foo interface {
Value() int
}
type bar struct {
value int
}
func (b bar) Value() int {
return b.value
}
type baz struct{}
func (b baz) Value() int {
return 42
}
I have a list of such guys
type Foos []Foo
var foos = Foos{
bar{},
baz{},
}
and I would like to traverse this list by changing the value of the members that have a value field.
for k := range foos {
change(&foos[k])
}
But I'm unable to find the right path
func change(g *Foo) {
t := reflect.TypeOf(g).Elem()
fmt.Printf("t: Kind %v, %#v\n", t.Kind(), t)
v := reflect.ValueOf(g).Elem()
fmt.Printf("v: Kind %v, %#v, %v\n", v.Kind(), v, v.CanAddr())
if f, ok := t.FieldByName("value"); ok {
fmt.Printf("f: %#v, OK: %v\n", f, ok)
vf := v.FieldByName("value")
fmt.Printf("vf: %#v: %v\n", vf, vf.CanAddr())
vf.SetInt(51)
}
}
As you can see, I'm not sure how to glue together the TypeOf and ValueOf bits...
The full example is on Go Playground.
There are a couple of issues here. First, it's not possible to set an unexported field. Here's a change to make the field exported:
type Foo interface {
// Rename Value to GetValue to avoid clash with Value field in bar
GetValue() int
}
type bar struct {
// export the field by capitalizing the name
Value int
}
func (b bar) GetValue() int {
return b.Value
}
type baz struct{}
func (b baz) GetValue() int {
return 42
}
The next issue is a bar interface value is not addressable. To fix this, use a *bar in the slice instead instead of a bar:
func (b *bar) GetValue() int {
return b.Value
}
...
var foos = Foos{
&bar{},
baz{},
}
With these changes, we can write the function to set the value:
func change(g Foo) {
v := reflect.ValueOf(g)
// Return if not a pointer to a struct.
if v.Kind() != reflect.Ptr {
return
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return
}
// Set the field Value if found.
v = v.FieldByName("Value")
if !v.IsValid() {
return
}
v.SetInt(31)
}
Run it on the playground
The above answers the question, but it may not be the best solution to the actual problem. A better solution may be to define a setter interface:
type ValueSetter interface {
SetValue(i int)
}
func (b *bar) Value() int {
return b.value
}
func (b *bar) SetValue(i int) {
b.value = i
}
func change(g Foo) {
if vs, ok := g.(ValueSetter); ok {
vs.SetValue(31)
}
}
Run it on the playground
Please don't use your current approach. It has several drawbacks.
It's confusing (as you've discovered)
It's slow. Reflection is always slow.
It's inflexible. Your loop, not the type itself, must understand the capabilities of each type implementation.
Instead, just expand your interface to include a setter method--possibly an optional setter method. Then you can loop through the items and set the value for those that support it. Example:
// FooSetter is an optional interface which allows a Foo to set its value.
type FooSetter interface {
SetValue(int)
}
// SetValue implements the optional FooSetter interface for type bar.
func (b *bar) SetValue(v int) {
b.value = v
}
Then make your loop look like this:
for _, v := range foos {
if setter, ok := v.(FooSetter); ok {
setter.SetValue(51)
}
}
Now when you (or a third party user of your library) adds a type Baz that satisfies the FooSetter interface, you don't have to modify your loop at all.
I am using testify to test my code and I want to check if a function was called.
I am doing the following:
type Foo struct {
mock.Mock
}
func (m Foo) Bar() {
}
func TestFoo(t *testing.T) {
m := Foo{}
m.Bar()
m.AssertCalled(t, "Bar")
}
The error I am getting:
Error: Should be true
Messages: The "Bar" method should have been called with 0 argument(s), but was not.
mock.go:419: []
I call function "Bar" and immediately ask if it was called but it returns false.
What am I doing wrong?
What is the proper way to test if a function was called with testify?
I tried with this and works:
type Foo struct {
mock.Mock
}
func (m *Foo) Bar() {
m.Called()
}
func TestFoo(t *testing.T) {
m := &Foo{}
m.On("Bar").Return(nil)
m.Bar()
m.AssertCalled(t, "Bar")
}
As stated by Chris Drew, you've to use a receiver pointer on Bar method's declaration.
Additionally, you've to istantiate a new structure as pointer and mock the method to return a value.
Looking at the documentation of testify I think you have to explicitly call func (*Mock) Called to tell the mock object that a method has been called.
func (m *Foo) Bar() {
m.Called()
}
There are some examples in the testify tests.
Make sure it is pointer receiver NOT value receiver.
This will always have nil Calls
type Foo struct {
mock.Mock
}
func (m Foo) Bar()
m.Called()
}
This will have N number of Calls
type Foo struct {
mock.Mock
}
func (m *Foo) Bar()
m.Called()
}
As an additional solution for when you want/need to use a value receiver, though not as clean, specifying Mock as a pointer field worked for me.
type Foo struct {
m *mock.Mock
}
func (f Foo) Bar() {
f.m.Called()
}
func TestFoo(t *testing.T) {
f := Foo{m: &mock.Mock{}}
f.Bar()
f.m.AssertCalled(t, "Bar")
}
I'm passing objects of two different structs to a function where it's compared with an existing object saved as interface {} type.
In the following how can I make two objects comparable for Equality ===
In this attempt, comparison with bar works fine but with foo it throws a panic error in spite both objects are of struct type
Go Playground
package main
import "fmt"
type Foo struct {
TestMethod func(str string)
}
type Bar struct {}
type IQux interface {
Compare(object interface{}) bool
}
type Qux struct {
Method func(str string)
Reference interface{}
}
func (qux Qux) Compare(object interface{}) bool {
return object == qux.Reference
}
func testMethod(str string) {
fmt.Println(str)
}
func main() {
foo := Foo{TestMethod:testMethod}
bar := Bar{}
ob := &Qux{Method: foo.TestMethod, Reference: foo}
ob.Compare(bar) // works fine
ob.Compare(foo) // panic: runtime error: comparing uncomparable type main.Foo
}
You have a little typo, just try:
package main
import "fmt"
type Foo struct {
TestMethod func(str string)
}
type Bar struct {}
type IQux interface {
Compare(object interface{}) bool
}
type Qux struct {
Method func(str string)
Reference interface{}
}
func (qux Qux) Compare(object interface{}) bool {
return object == qux.Reference
}
func testMethod(str string) {
fmt.Println(str)
}
func main() {
foo := &Foo{TestMethod:testMethod}
bar := Bar{}
ob := Qux{Method: foo.TestMethod, Reference: foo}
ob.Compare(bar) // works fine
ob.Compare(foo) // panic: runtime error: comparing uncomparable type main.Foo
}
So I'd like to have a map of names of functions, to choose an implementation of an interface based on an environment variable. I've reproduced it in the following code:
package test
type Fooer interface {
Foo() error
}
type Bar struct{}
func NewBar() (*Bar, error) { return &Bar{}, nil }
func (b *Bar) Foo() error { return nil }
type Baz struct{}
func NewBaz() (*Baz, error) { return &Baz{}, nil }
func (b *Baz) Foo() error { return nil }
var constructors map[string]func() (*Fooer, error)
func init() {
constructors = map[string]func() (*Fooer, error){
"bar": NewBar,
"baz": NewBaz,
}
}
This throws the following errors when I go build test.go:
./test.go:21: cannot use NewBar (type func() (*Bar, error)) as type func() (*Fooer, error) in map value
./test.go:22: cannot use NewBaz (type func() (*Baz, error)) as type func() (*Fooer, error) in map value
So what am I doing wrong? Can I use a *Fooer as the return type of a constructor function? What would be the actual best way to approach this? (I'm new to Go)
Do not (almost never) pass around pointers to interface. You will (almost) never need a *Fooer, a Fooer is enough.
Yes, your Bar and Baz constructors could return a Fooer (not a *Fooer!) but that seems awkward.
Keeping the constructors in a map and querying the map for a constructor seem like one level of indirection too much. Are you constantly creating new Bar and Baz?