Here are golang code, the func newXXX return an interface, but why it does not return a struct
type _ABitOfEverythingServer struct {
v map[string]*examples.ABitOfEverything
m sync.Mutex
}
type ABitOfEverythingServer interface {
examples.ABitOfEverythingServiceServer // interface
examples.StreamServiceServer // interface
}
func newABitOfEverythingServer() ABitOfEverythingServer {
//<-why not return _ABitOfEverythingServer, is it a good way?
return &_ABitOfEverythingServer{
v: make(map[string]*examples.ABitOfEverything),
}
}
First, you need to learn the basics of Go. Take A Tour of Go.
Simplifying a complicated example,
package main
import "fmt"
type S struct{ F int }
type I interface{}
func newI() I {
return &S{F: 42}
}
func main() {
i := newI()
s := i.(*S)
f := s.F
fmt.Println(f)
}
Playground: https://play.golang.org/p/tHbTZHEQZ-L
Output:
42
The newI
function returns a value of interface type I
, which contains a value of concrete type *S
.
I do not know if there was any particular reason for returning interface in the above snippet.
But generally, returning structs is the recommended way. Remember Accept interfaces, return structs
anyone?
Returning interfaces does not simplify mocking in anyway since client can define interface when mocking is required (which is the most beautiful thing about golang interfaces).
func newABitOfEverythingServer() *_ABitOfEverythingServer { // <- returning struct ptr
return &_ABitOfEverythingServer{
v: make(map[string]*examples.ABitOfEverything),
}
}
For the above refactored version (which returns structs), client can simply define an interface describing what it needs and mock only that:
type onlyStreamPart interface {
examples.StreamServiceServer
}
// streamer does not care if the streamServer also
// implements examples.ABitOfEverythingServiceServer
// or not. (Think interface segregation from SOLID)
func streamer(stremServer onlyStreamPart) {
}
// which can be called easily as:
streamer(newABitOfEverythingServer())
This simplifies mocking a lot while testing streamer
since the mock implementation does not have to implement examples.ABitOfEverythingServiceServer
interface.
This is a commonly misunderstood by developers from Java, C# etc. backgrounds (where type systems are name based, not structural as in Go). Since in those languages client cannot modify the interface it is accepting because that would require adding implements newInterfaceDefinedByClient
clause to all the classes that need to be passed to the client.