In following code snippet -
type Input interface {
Name() string
}
type Abc interface {
Do(Input)
}
type InputImpl struct {
}
func (InputImpl) Name() string {
return "sample-impl"
}
type AbcImpl struct {
}
func (abcImpl *AbcImpl) Do(input Input){
// do something
}
AbcImpl struct is an implementation of Abc interface, but changing last function like this -
func (abcImpl *AbcImpl) Do(input InputImpl){
// do something
}
Now the AbcImpl is not implementing Abc anymore, though InputImpl is implementing Input interface !
Am I missing something or it's compulsory to have exact same signature (not event Impls) as the interface to be a legitimate implementation?
Yes, you do have to follow the method signature you specified.
If you don't follow the signature, it will not be called "implementing".
an example: interface example
from tour of Go: There is no explicit declaration of intent, no "implements" keyword.
It is compulsory to use the very exact same signature when implementing an interface in Go. You can't implement it otherwise.
Related
I would like to access an internal property in a custom constructor, in my case it's a property from a superclass, like this:
type BaseRepository struct {
database mongo.Database
}
type PointRepository struct {
BaseRepository
pointCollection mongo.Collection
}
func NewPointRepository() *PointRepository {
pointCollection := ***self***.database.GetCollection("points")
pr := &PointRepository{
pointCollection: pointpointCollection,
}
}
As you can see, I need to access something like self to this approach works.
How can I workaround this situation?
There are no constructors or classes in Go.
PointRepository embeds BaseRepository, which has an unexported database field. Any function in the same package as BaseRepository can directly access the database field.
If you need to access that field from a function outside the package, you either have to export it, or you have to provide an exported getter method in BaseRepository.
Solution 1:
Add Set function for BaseRepository
Solution 2:
use unsafe package
type BaseRepository struct {
database string
}
type PointRepository struct {
BaseRepository
pointCollection string
}
baseRepository := &internel.BaseRepository{}
databasePointer := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(baseRepository))))
*databasePointer = "changed here"
fmt.Printf("%+v",baseRepository)
output:
&{database:changed here}
This is just an example, you should change the type of the field database.
I am an ex python dev sometimes struggling with the explicit nature of Go.
I am trying here to refactor some code in order to be able move a method from one structure to be part of an interface.
But the process seems weird to me, I wish to confirm I am not doing something incorrectly.
I have the following interfaces, structure and methods:
type Executing interface {
Execute()
}
type MyExecuter struct {
attribut1 string
}
//The function I wish to move
func (exe1 *MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 *MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
func GetExecuter () Executer{
return MyExecuter{attribut1: "test"}
}
So here I have a generic interface Execute, this interface will be accessed by the object returned by the GetExecuter method.
Now, as part of the implementation of one of my Executer, I want to move the Format method as part of an interface.
So I am doing the following:
type Formatting interface {
format() string
}
type Formatter struct {}
func (formatter *Formatter) format(exe1 *MyExecuter) (string) {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
So I create a new interface, a new empty structure, and update my function to take as attribute my previous structure.
While this seems to work, it seems to me this is a bit convoluted. Specially the part where I need to add a reference to my initial object as attribute of the method. Am I doing something wrong here, or this is the right way?
Your Executer implementation already implements the Formatting interface:
type Executing interface {
Execute()
}
type Formatting interface {
format() string
}
func (exe1 MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
v:=MyExecuter{}
// Here, v implements Executing and Formatting interfaces
One thing to note here: Your code shows pointer receivers. That means the methods are defined for *MyExecuter, but not for MyExecuter. So you have to pass pointers to the struct instance for this to work. Or, as I did above, use the value receivers so the methods are defined for both MyExecuter and *MyExecuter.
Trying to mock struct for testing. But following code has an error:
./test.go:32:17: cannot use NewClass() (type *Class) as type mockClass in return argument:
*Class does not implement mockClass (wrong type for Query method)
have Query() *Iterator
want Query() mockIterator
Why I can't do that?
func NewClass() *Class {
return &Class{}
}
type Class struct{}
func (Class) Query() *Iterator {
return &Iterator{}
}
type Iterator struct{}
func (Iterator) Next() error {
return nil
}
type mockClass interface {
Query() mockIterator
}
type mockIterator interface {
Next() error
}
var newMock = func() mockClass {
return NewClass()
}
In the test I want to assign to newMock something like:
newMock = funcr() mockClass {
return &fakeClass{}
}
The structs Class and Iterator are not under my control. Those structs come from external library.
Create an interface that expresses business logic that your component needs. Do not use any 3rd party types.
Use that interface in your business logic.
Create an implementation of this interface wrapping 3rd party library and pass it to your component in main.go, which is a good place to wire/inject various system components.
That way you can easily mock your interface and change the implementation for another if one day you decide not to use this 3rd party library.
If for some reason you are tied to this library and there is no way to create an interface not referencing 3rd party types, then have a look at the Can I mock out library code with a nested interface?
is there any solution to force struct have specific property(defined in interface)?
or define a property(attribute,field) in interface?.
as i see interface is always accept method not property?. (https://gobyexample.com/interfaces)
type geo interface {
PrintType()
typ string//not function , but field
}
type circle struct {
typ string
}
func (c circle) PrintType() {
fmt.Println(c.typ)
}
thanks
Interfaces are about methods only, not properties, because interfaces are about behavior. So there is no way to force a struct to have something. Rather the preferred method is to have an accessor to that member.
I recently came across a code that is doing something I don't understand.
There are multiple structs having the same embedded struct and an interface that defines methods returning pointer to each struct. This interface is implemented by the embedded struct but only 'partially' by the individual structs, as such, each struct only implements the method where the pointer to that struct is returned.
For better understanding, here is the representative code:
type BarStocks interface {
GetVodka() *Vodka
GetMartini() *Martini
GetBourbon() *Bourbon
GetNegroni() *Negroni
GetManhattan() *Manhattan
}
type BaseAttributes struct {
ID uuid.UUID
Quantity float64
CreatedAt time.Time
UpdatedAt time.Time
}
func (e *BaseAttributes) GetVodka() *Vodka {
return nil
}
func (e *BaseAttributes) GetMartini() *Martini {
return nil
}
func (e *BaseAttributes) GetBourbon() *Bourbon {
return nil
}
func (e *BaseAttributes) GetNegroni() *Negroni {
return nil
}
func (e *BaseAttributes) GetManhattan() *Manhattan {
return nil
}
And then each individual struct implements only the method where its pointer is returned, for example:
type Vodka struct {
BaseAttributes
Label string
}
func (v *Vodka) GetVodka() *Vodka {
return v
}
Now in the code, this setup is used to typecast the individual struct to the interface as a pointer, something like this:
func someFunc() BarStocks {
v := Vodka{}
return &v
}
Now I am not too deep into Go yet and so unable to comprehend how the pointer to the struct becomes the same type as the interface.
Thanks in advance for any insight into this.
I'll do my best to answer the question I think you're asking.
The documentation on embedding explains the behavior you're seeing,
There's an important way in which embedding differs from subclassing.
When we embed a type, the methods of that type become methods of the
outer type, but when they are invoked the receiver of the method is
the inner type, not the outer one.
This explains how a Vodka struct, which embeds struct BaseAttributes which implements all of the methods in BarStocks is able to satisfy the interface Barstocks. This excerpt, however, does not explain how we effectively override GetVodka() for our Vodka struct.
To understand this we need to read another excerpt from the documentation.
Embedding types introduces the problem of name conflicts but the rules
to resolve them are simple. First, a field or method X hides any other
item X in a more deeply nested part of the type.
This excerpt explains that If Vodka implements GetVodka() and embeds a struct (BaseAttributes) which also implements GetVodka(), the outer-most definition is the one that takes precedence.
The combination of these behaviors explain how Vodka satisfies the BarStocks interface and has the behavior you see in the example code.
The additional methods missing from Vodka, but present on BarStocks are implemented for BaseAttributes and if the method is missing from Vodka, the method from the embedded strut will be called instead.
Note, methods in an embedded struct will not have access to the parent struct members. Also note, if you wanted to call the embedded struct's method when it has been defined in the parent (as GetVodka is for Vodka) then you would prepend the embedded type's name to the method. For example
myDrink := someFunc()
myDrink.BaseAttributes.GetVodka()
This is obviously not helpful in this case as all of the BaseAttribute methods return nil, but may be helpful in the future.