Type Composition: overriding interface types - go

I want to compose a type of another type, but replace one of the fields (which is an interface value) with a fake. The problem I am getting is the underlying field is being used, so I can't seem to override the field.
I've demoed the problem here: https://play.golang.org/p/lHGnyjzIS-Y
package main
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct {}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client PrinterService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct {}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func main() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}
Why does it print "PrinterService"? I want it to print "SomeOtherService".
Thanks.

By s.PrintViaMethod(), you are calling the promoted method FakeService.Service.PrintViaMethod(), and the method receiver will be FakeService.Service which is of type Service, and Service.PrintViaMethod() calls Service.Client.Print(), where Service.Client is of type which PrinterService, that's why it prints "PrinterService".
In Go there is embedding, but there is no polymorphism. When you embed a type in a struct, methods of the embedded type get promoted and will be part of the method set of the embedder type. But when such a promoted method is called, it will get the embedded value as the receiver, not the embedder.
To achieve what you want, you would have to "override" the PrintViaMethod() method by providing your implementation of it for the FakeService type (with FakeService receiver type), and inside it call FakeService.Client.Print().
By doing so s.PrintViaMethod() will denote the FakeService.PrintViaMethod() method as that will be at the shallowest depth where the PrintViaMethod() exists (and not FakeService.Service.PrintViaMethod()). This is detailed in Spec: Selectors.
For example:
func (fs FakeService) PrintViaMethod() {
fs.Client.Print()
}
Then the output will be (try it on the Go Playground):
SomeOtherService
See related questions and answers with more details:
Go embedded struct call child method instead parent method
Does fragile base class issue exist in Go?

Why does it print 'PrinterService'? I want it to print 'SomeOtherService'.
Because that's what your code says to do. PrintViaMethod calls s.Client.Print(), and s.Client is a (zero value) instance of PrinterService, which outputs PrinterService.
What you probably want is to call s.Print() in main(). I don't see any reason for your PrintByMethod function at all.

As per Flimzy you are calling print s.Client.Print() which is of type PrinterService implemented as receiver to Print() function printing PrinterService. You can also change type of Client PrinterService in Service struct to Someother service
package embedded
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct{}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client SomeOtherService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct{}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func Call() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}

Related

what is the actual difference between &Struct{field: "blabla"} and Struct{field: "blabla"} (without memory address symbol)?

i.e.
package main
import "fmt"
type rabbit struct {
food string
}
func (r *rabbit) test() {
fmt.Println(r.food)
}
func main() {
roger := &rabbit{"carrot"} //rabbit{"carrot"} would have done the same thing
roger.food = "salad"
roger.test()
}
whether you define roger as &rabbit{"carrot"} or rabbit{"carrot"}, you can in any case change its attributes and call pointer receivers. But if you had to implement an interface like in this example
package main
import "fmt"
type interfaccia interface {
test()
}
type rabbit struct {
food string
}
func (r *rabbit) test() {
fmt.Println(r.food)
}
func someFunc(elemento interfaccia) {
elemento.test()
}
func main() {
roger := &rabbit{"carrot"} //without pointer receiver you would bump into an error
someFunc(roger)
}
then you are forced to set roger as pointer receiver due to the interface. and if I had a recursive struct like this:
type rabbit struct {
food string
girlfriend *rabbit
}
then I'm always forced to use the pointer.
My concern is: since &rabbit{"carrot"} includes all things of rabbit{"carrot"}, why should I use the last one?
A method of a type can either have a pointer receiver or a value receiver. There is a caveat while pointer vs value receiver for methods of a type when that type implements an interface
If a type implements all methods of an interface using value receiver, then both value and pointer of that type can be used while assigning to that interface variable or while passing to a function which accept an argument as that interface.
If a type implements all methods of an interface using pointer receiver, then the only pointer of that type can be used while assigning to that interface variable or while passing to a function that accepts an argument as that interface.
see the example in go tour here

Type Assertion vs Importing Interface

I'm working on a project that would require some level of abstraction on some data and I would like to keep the packages that use the data as independent as possible so I can swap things out in the future.
Here are 2 possible ways that I thought of, one is having a common data interface and have all the places import it. The other is to have each package define its own interfaces and do a type assertion.
Which is the most Go/general way of doing it?
// Importing interface
// src/model
type IData interface {
myint() int
}
// src/dataextractor
import src/model
type DataExtractor struct {
foo() IData
}
// src/service
import src/model
type ServiceDataExtractor interface {
foo() IData
}
type Service struct {
extractor ServiceDataExtractor
}
func (s Service) serve() {
v = s.extractor.foo()
// do stuff with v
}
vs
// type assertion
// src/dataextractor
type DataExtractorData struct{}
func (d DataExtractorData) myint()int {}
type DataExtractor struct {
foo() interface{} {
reutrn DataExtractorData{}
}
}
// src/service
type ServiceData interface {
myint() int
}
type ServiceDataExtractor interface {
foo() interface{}
}
type Service struct {
extractor ServiceDataExtractor
}
func (s Service) serve() {
data := s.extractor.foo()
v, ok := data.(ServiceData)
// do stuff with v
}
Here's the simple rules to keep in mind. An interface type should be declared in the package that wants to receive that interface type. To satisfy an interface, you don't have to import it. All you need to do is declare the methods as are specified by the interface.
When do you use interfaces? Typically, when you have a field, or parameter, that you want to be able to accept multiple data types, and you can do all you need to do with it by calling methods. How do you determine what goes in the interface? You simply ask yourself: "What methods would I need to call on this value to make use of it?"
The only seemingly meaningful method in your example is myint() int, and the only place it seems you intend to use it is in Service.
type Service struct {
extractor interface {
myint() int
}
}
func (s Service) serve() {
s.extractor.myint()
}

Can't I use pointer to the type of interface in Go?

I write the code with DI as follows. There are 2 code. One is for use case and other is controller that depend on that use case.
Use Case
package usecase
import "fmt"
type Interface interface {
Echo() string
}
type UseCase struct {}
func (u *UseCase) Echo() string {
return fmt.Sprintf("this is usecase!")
}
Controller
package controller
import (
"my-project/usecase"
)
type Controller struct {
usecase *usecase.Interface
}
func NewController(useCase *usecase.Interface) *Controller {
return &Controller{
usecase: useCase,
}
}
func (s *Controller) Hello() {
result := s.usecase.Echo()
println(result)
}
However, in the controller the following error message was displayed.
Unresolved reference 'Echo'
The type of field usecase in the controller structure Controller is *usecase.Interface. (pointer)
The reason is that the Echo() method of UseCase, which implements the interface, is a pointer receiver.
I can't use a pointer to the interface as follows?
type Controller struct {
usecase *usecase.Interface
}
Change your code to:
type Controller struct {
usecase usecase.Interface
}
func NewController(useCase usecase.Interface) *Controller {
return &Controller{
usecase: useCase,
}
}
func (s *Controller) Hello() {
result := s.usecase.Echo()
println(result)
}
There's almost never any reason to use a pointer to an interface. The only time you would want a pointer to an interface, is when you need to set an interface value, which is passed as a function argument. i.e.:
var x SomeInterface
SetX(&x)

Generic approach and recommendation how to remove dependency

I have a question regarding dependency injection.
Please consider the example below.
For example, selector() is a function that select something and guarantee return an interface
In this example
bar.node.go
type NodeTemplate struct {
Name string
}
// satisfy interface declared in db.foo.go
//but never imports anything from db.foo.go
func (node *NodeTemplate) GetUuidName() string {
if node != nil {
return node.Name
}
return
}
db.foo.go
// interface declared in db.foo.go
type Node interface {
GetUuidName() string
}
Option A
// So selector receives a map of Some interface and populate a map
func SelectSomething(nodemap map[string]Node, selectFactor string) {
// selection from db and result populate in a map
}
Option B
Another pattern SelectSomething return a Node
and it Interface
So another package will depend on importing Node
and that will introduce a dependency.
func SelectSomething(seleconsomething) []*Node {
// do selection and return a slice of SomeInterface
n := &Node{} // here it need to be concret type T
return Node
}
So based on logic I've described I see the first approach is better but in that approach, select need do concrete type allocation in order to populate a map.
Consider another example
db.foo.go
type Node interface {
GetUuidName() string
}
func inserter(node *Node) error {
// do some work
node.GetUuidName()
}
For a case like in inserter case, inserter has no external dependency, inserter just needs to receive something that satisfies the interface. Declare interfaces locally and that brake a dependancy.
But in the case of selector example, it has to do memory allocation in order to return or populate a map or return something that has concrete type T. So in both case, it has to have internal re-presentation.
So here is my question can selector somehow at run time figure out a type it receives based on the interface and instantiate an object of that type and insert to a map as an interface or return a slice of the interface. ?
By doing so selector function will have no dependancy on what it receives it just guarantee it will instantiate the same object type T
and return interface.
or can selector return interface but I guess I have to have a bi-directional interface between db package and package X or dynamic dispatcher need to do some magic ?
You want a type to behave in a certain way. That is achieved via an interface. This case is no different. Simply add the desired behavior to your interface, as demonstrated below with the Foo interface.
package main
import (
"fmt"
"reflect"
)
type Foo interface {
Bar()
TypeOf() reflect.Type
}
type Baz struct{}
func (b Baz) Bar() {
fmt.Println("I am a Fooer!")
}
func (b Baz) TypeOf() reflect.Type {
return reflect.TypeOf(b)
}
func DoSomeThing(f Foo) {
f.Bar()
fmt.Println(f.TypeOf())
}
func main() {
fmt.Println("Hello, playground")
b := Baz{}
DoSomeThing(b)
}
Run on playground

Golang method with pointer receiver [duplicate]

This question already has answers here:
X does not implement Y (... method has a pointer receiver)
(4 answers)
Closed 3 years ago.
I have this example code
package main
import (
"fmt"
)
type IFace interface {
SetSomeField(newValue string)
GetSomeField() string
}
type Implementation struct {
someField string
}
func (i Implementation) GetSomeField() string {
return i.someField
}
func (i Implementation) SetSomeField(newValue string) {
i.someField = newValue
}
func Create() IFace {
obj := Implementation{someField: "Hello"}
return obj // <= Offending line
}
func main() {
a := Create()
a.SetSomeField("World")
fmt.Println(a.GetSomeField())
}
SetSomeField does not work as expected because its receiver is not of pointer type.
If I change the method to a pointer receiver, what I would expect to work, it looks like this:
func (i *Implementation) SetSomeField(newValue string) { ...
Compiling this leads to the following error:
prog.go:26: cannot use obj (type Implementation) as type IFace in return argument:
Implementation does not implement IFace (GetSomeField method has pointer receiver)
How can I have the struct implement the interface and the method SetSomeField change the value of the actual instance without creating a copy?
Here's a hackable snippet:
https://play.golang.org/p/ghW0mk0IuU
I've already seen this question In go (golang), how can you cast an interface pointer into a struct pointer?, but I cannot see how it is related to this example.
Your pointer to the struct should implement the Interface. In that way you can modify its fields.
Look at how I modified your code, to make it working as you expect:
package main
import (
"fmt"
)
type IFace interface {
SetSomeField(newValue string)
GetSomeField() string
}
type Implementation struct {
someField string
}
func (i *Implementation) GetSomeField() string {
return i.someField
}
func (i *Implementation) SetSomeField(newValue string) {
i.someField = newValue
}
func Create() *Implementation {
return &Implementation{someField: "Hello"}
}
func main() {
var a IFace
a = Create()
a.SetSomeField("World")
fmt.Println(a.GetSomeField())
}
The simple answer is that you won't be able to have the struct implement your interface while having SetSomeField work the way you want.
However, a pointer to the struct will implement the interface, so changing your Create method to do return &obj should get things working.
The underlying problem is that your modified SetSomeField method is no longer in the method set of Implementation. While the type *Implementation will inherit the non-pointer receiver methods, the reverse is not true.
The reason for this is related to the way interface variables are specified: the only way to access the dynamic value stored in an interface variable is to copy it. As an example, imagine the following:
var impl Implementation
var iface IFace = &impl
In this case, a call to iface.SetSomeField works because it can copy the pointer to use as the receiver in the method call. If we directly stored a struct in the interface variable, we'd need to create a pointer to that struct to complete the method call. Once such a pointer is made, it is possible to access (and potentially modify) the interface variable's dynamic value without copying it.

Resources