How to use interface methods in main file in go? - go

I have an interface in the service package
databaseService.go
package service
import "gitlab.com/xert/customerservice/internal/database/models"
type CustomerdetailsServiceInterface interface {
// Remove deletes a user by user name from database.
Add()
}
Then I have another service file customerDetailsService.go,where i am implementing the interface methods
type CustomerdetailService struct {
}
func Add(ud *CustomerdetailService) {
fmt.Println("hello")
}
Now when I am trying to use it my main.go
import (
"gitlab.com/xert/customerservice/internal/database/service"
)
func main() {
service.CustomerdetailsServiceInterface.Add() // this is complaining too few arguments
}
How to call the method like this, implement methods in other file?

You have not implemented CustomerdetailsServiceInterface in the first place. Following is the way you can implement it.
type CustomerdetailService struct {}
func (ud *CustomerdetailService) Add() {
fmt.Println("hello")
}
See the following code, hope it will help you understanding interface in go.
package main
import (
"fmt"
)
type CustomerdetailsServiceInterface interface {
Add()
}
type CustomerdetailService struct{}
func (ud *CustomerdetailService) Add() {
fmt.Println("hello")
}
type AnotherCustomerdetailService struct{}
func (ud *AnotherCustomerdetailService) Add() {
fmt.Println("Modified Addition")
}
func main() {
var x CustomerdetailsServiceInterface
x = &CustomerdetailService{}
x.Add()
x = &AnotherCustomerdetailService{}
x.Add()
}
You can not call a method directly on interface but you will need a variable with a type which implements the interface. In the above case it's CustomerdetailService which implements CustomerdetailsServiceInterface.

Related

Why can't I call an interface with a collection of methods from the main package

I am really new to golang and I am trying to see how encapsulation really works in go.
I have the following structure
-- package a
-a_core.go
-a.go
-models.go
-- main.go
In models.go I have structs for request and responses for an api call,
a.go has an empty struct, which is private and a public interface, which I want to expose with various methods
a_core.go just has some business logic which would be called in my interface implementation
Then, I have a main.go where I just call the public interface.
code in a.go
package a
type myFunction struct{}
type MyFunc interface {
Create(myData *MyData) (*MyData, error)
Fetch(test string)
Delete(test string)
}
//Concrete implementations that can be accessed publicly
func (a *myFunction) Create(data *MyData) (*MyData, error) {
return nil, nil
}
func (a *myFunction) Fetch(test string) {
}
func (a *myFunction) Delete(test string) {
}
In main.go, I call the interface my first create the MyData pointer with values
data := &a.MyData{
/////
}
result, err := a.MyFunc.Create(data)
I get the following error when I do this,
too few arguments in call to a.MyFunc.Create
cannot use data (variable of type *a.MyData) as a.MyFunc value in argument to a.MyFunc.Create: missing method CreatecompilerInvalidIfaceAssign
Please what am I doing wrong?
Here is an example
Note that names in uppercase are public, in lowercase private (see https://tour.golang.org/basics/3 )
./go-example/main.go
package main
import "go-example/animal"
func main() {
var a animal.Animal
a = animal.Lion{Age: 10}
a.Breathe()
a.Walk()
}
./go-example/animal/animal.go
package animal
import "fmt"
type Animal interface {
Breathe()
Walk()
}
type Lion struct {
Age int
}
func (l Lion) Breathe() {
fmt.Println("Lion breathes")
}
func (l Lion) Walk() {
fmt.Println("Lion walk")
}

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)

Methods dispatch using interface in Go

How is actually methods in Go get dispatched if we use interface, static(compile time) or dynamic(run time). Let consider this code:
package main
import "fmt"
type ICat interface {
Meow()
Walk()
Run()
}
func NewCat(name string) ICat {
return &cat{
name:name,
}
}
type cat struct {
name string
}
func (c *cat) Meow() {
fmt.Print("Meowwwwwwwww")
}
func (c *cat) Walk() {
fmt.Print("Walk")
}
func (c *cat) Run() {
fmt.Print("Run")
}
type IAnimal interface{
DoSound()
}
type animal struct {
cat ICat
}
func New() IAnimal {
return &animal{
cat:NewCat("bobby"),
}
}
func (a *animal) DoSound() {
a.cat.Meow()
}
func main() {
i := New()
i.DoSound()
}
Go Playground: https://play.golang.org/p/RzipDT6FAC9
How actually those methods defined in those interface got dispatched?, I use this style of development to implement interface segregation and separation of concern between data and behaviour. My other concern is the perf. Some said it's statically dispatched at compile time, while other said it's dynamically dispatched at run time.
We cannot know at compile time what the dynamic type of an interface value will be, A call through an interface must use dynamic dispatch. Instead of a direct call, the compiler must generate code to obtain the address of the method from the type descriptor, then make an indirect call to that address.

How to call only specific functions that have an annotation or tag

Is there a way to add a tag or annotate some methods so that whenever an event arises all the methods with this tag or annotation get invoked?
How to achieve this in Go?
As others have said, no there are no annotations or tags on functions in Go.
However, it is more than possible to use a map (or slice) and a register function to keep records of other funcs (or interfaces). You just need to manually call that register func (usually in init() of that package).
For example,
package events
var eventFuncs = make(map[string]func())
func Register(event string, f func()) {
eventFuncs[event] = append(eventFuncs[event],f)
}
func Get(event string) []func() {
return eventFuncs[event]
}
And using the package to register:
package xy
import (
"fmt"
"some.url/events"
)
func Call() {
fmt.Println("Ha!")
}
func init() {
events.Register("x",Call)
}
And then call the funcs elsewhere:
package main
import (
"some.url/events"
)
func main() {
for _,f := range pkg.GetEvent("x") { f() }
}

Overwrite anonymous struct function

How can I overwrite anonymous struct function.
To clarify what I mean look at the following code snippet:
package base
import (
"fmt"
"net/http"
)
type Executer interface {
Execute()
}
type Controller struct { }
func (self *Controller) Execute() {
fmt.Println("Hello Controller")
}
func (self *Controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
self.Execute()
}
Now I am embedding the Controller struct into Test struct, also called anonymous
package base
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
type Test struct {
Controller
}
func (self *Test) Execute() {
fmt.Println("Hello Test")
}
func TestInheritance(t *testing.T) {
ts := httptest.NewServer(&Test{})
defer ts.Close()
http.Get(ts.URL)
}
As output I've got "Hello Controller" but expected "Hello Test". You can see code above, I reimplement the execute function, but it does not work.
Since Test has no ServeHTTP method, your test server uses Controller's, which calls Controller.Execute(). If you want it to work properly, define ServeHTTP for the Test type.
type Test struct {
Controller
}
Controller has no ServeHTTP method but *Controller has. So
type Test struct {
*Controller
}
I think it will work.

Resources