Providing Access to package level variable via public getter - How to return the instance? - go

I have a package level variable that I instantiate at the startup of the application. Even though it is declared to be package level, I need to access it from outside the package as well. To do that, I have a function that returns the variable.
package app
var myService MyService
type MyService interface {
DoThis()
DoThat()
}
func Initialize() {
// initialise other stuff
myService = initMyService()
}
func GetMyService() MyService {
return myService
}
Now from outside of the app package, when I need to do something with MyService, I do following.
ms := app.GetMyService()
ms.DoThis()
Here I have following questions.
Doesn't the GetMyService() function return copies of myService each time it is invoked?
If that is the case, if I return a pointer to the myService inside that function, does it solve that problem by returning a reference to the single myService instance that was initially instantiated?

var myService MyService here MyService is an interface. So you can implement it with pointer receiver methods or value receiver methods.
As go tour tour.golang.org/methods/8 mentioned,
There are two reasons to use a pointer receiver.
The first is so that the method can modify the value that its receiver
points to.
The second is to avoid copying the value on each method call. This can
be more efficient if the receiver is a large struct...
If you implement MyService with pointer receiver methods, It will not copy the receiver in every call.
And please refer golang.org/doc/faq Should I define methods on values or pointers?. There is a good explanation for it too.
sample implementation like below
type doer struct {
// any fields
}
func (d *doer) DoThis() {
// any implementation
fmt.Println(`do this`)
}
func (d *doer) DoThat() {
// any implementation
fmt.Println(`do that`)
}
func initMyService() MyService{
return &doer{
// init doer fields
}
}

Related

Why does Go allow a struct to implement an unexported interface present in a different package?

I wrote a sample code to understand how the unexported interface works. In the below example, I have declared the unexported repoInterface in the service package.
TestRepo struct in the repo package implements the unexported repoInterface without any issues.
Code structure
repo
repo.go
service
service.go
main.go
service.go
// service/service.go
// this is the interface which the TestRepo struct implements in repo package
type repoInterface interface{
GetName() string
}
type TestService struct{
repo repoInterface
}
func NewTestService(r repoInterface) TestService {
return TestService{
repo: r,
}
}
func (s TestService) GetName() string {
return s.repo.GetName()
}
repo/repo.go
// repo/repo.go
type TestRepo struct{
name string
}
func NewTestRepo(name string) TestRepo {
return TestRepo{
name: name,
}
}
// implements repoInterface present in service package
func (r TestRepo) GetName() string {
return r.name
}
main.go
func main() {
testRepo := repo.NewTestRepo("hello")
testService := service.NewTestService(testRepo)
fmt.Println(testService.GetName())
}
// Output
// hello
My assumption so far:
This isn't possible since repo and service
are different packages.
TestRepo struct present in repo package cannot implement the Unexported interface present in the service package.
This is the reason why we export interfaces.
Now I realized that this is not true and my understanding is wrong.
Question:
Why does Go allow to implement an unexported interface present in a different package?
service.NewTestService package function requires any value that implements the type interface{ GetName() string }.
repo package exports a type TestRepo which exposes a method GetName() string.
Upon passing the repo.TestRepo to the service.NewTestService function like in service.NewTestService(testRepo), the value implements the interface by providing the expected method set.
All good.
That the type service.repoInterface declares a not exported identifier only discriminates the packages that can use that interface name.
I have reproduced your example on the play https://go.dev/play/p/bp6z2HjwdLS
An interface type declaration containing a not exported identifier is a sealed interface.
Those sealed interfaces can not be implemented by a foreign package.
It can be a not exported method name like in
type Fooer interface {
Foo()
sealed()
}
Try here https://go.dev/play/p/3Syh7R0uS-q
It can also declare a method using a not exported argument type,
type Foo interface {
GetName() string
GetName2() sealed
}
type sealed int

Golang package interface

I am bit new to golang and I have a question about packages and interfaces.
If I have package1, that needs to use implementation of an interface that can be swapped in future with other implementation, would that be possible?
some pseudo code
package implementation contains current implementation of interface
type TestI interface {
M1()
}
package implementation
type Impl struct {}
funct (i *Impl) M1 ( ... do something )
package package1
import TestI somehow and call M1 method but with flexibility to swap it with other implementation of this interface in future?
package package1 should use implementation without knowing about it (something like DI in c# or java, package should only know about interface, and not about implementation)
Where should TestI interface be defined? Sorry if this is a bit confusing, just trying to get my head around it.
This is equivalent in c#
ITest {
SetClass(Class1 cl);
}
// package1
class Class1 {
private ITest test {get; set;}
public void SomeMethod() {
// i want to somehow set this in other package
test.SetClass(this);
}
}
// package2
class Test implements ITest {
private Class1 cl;
SetClass(Class1 c) {
this.c1 = c;
}
}
Unless you are writing an interface-first application, it is generally best to write the concrete implementations without declaring any interfaces. Then the users of that package can declare the necessary interfaces. For example:
type Implementation struct {
...
}
func (i Implementation) FuncA() {...}
func (i Implementation) FuncB() {...}
If some type that implements FuncA is required, you can declare:
type IntfA interface {
FuncA()
}
Any type that has the method FuncA implements IntfA, and Implementation fits that description, so you can pass an instance of Implementation to a function that needs IntfA.
Similarly, if you need an interface that has both FuncA and FuncB, you can declaret:
type IntfAB interface {
FuncA()
FuncB()
}
and Implementation also implements IntfAB.
So, ideally, you would declare the interface you need where you use it, and any type with a matching set of methods can be used for the implementation of that interface.
If you are writing based on an existing interface, then you can put that interface in a separate package than the implementation, or you can keep the interface and the implementation in the same package, whichever makes more sense for your use case.

Embeded interface : struct doesn't implement method

I don't understand why interface composition doesn't " inherit" the methods from the parent interface when it is satisfied in the implementation.
package main
import (
"fmt"
)
type TestRepository interface {
FindById(int) (error)
}
type TestService interface {
TestRepository
Method(id int) error
}
type testService struct {
implRepository TestRepository
}
func NewTestService(r TestRepository) TestService {
return &testService{implRepository: r}
}
When compiling this code i'm getting : *testService does not implement TestService (missing FindById method) while i'm actually expecting it to implement it since the type of "implRepository" is TestRepository.
It works if i do :
func NewTestService(r TestRepository) *testService {
return &testService{implRepository: r}
}
But it kind of defeat the purpose of the interface ( as far as the service one goes at least )
What am i missing / how should it be done ?
The answer to your question is simply "you aren't composing the interface the way you need to." You have made TestRepository a struct member - that is not going to "inherit" the methods on that interface. What you need is the following:
type testService struct {
TestRepository
}
func NewTestService(r TestRepository) TestService {
return &testService{TestRepository: r}
}
Of course, the struct testService still need to implement Method(id int) error to actually work.

How to mock a particular method of a spring bean

I have a spring bean with multiple APIs. Mocking the bean doesn't serve my purpose as I would like to verify fetchFromDb() called only once on multiple calls to getCachedData() with the same input. This is to make sure the result is cached.
Is it possible to mock fetchFromDb() on bean 'market' while calling getCachedData()?
Sample Class
#Configuration("market")
public class AllMarket {
#Autowired
private CacheManager cachedData;
public boolean getCachedData(LocalDate giveDate) {
//check if it exists in cache
if(Objects.nonNull(checkCache(giveDate)) {
return checkCache(giveDate);
}
//fetch from database
boolean bool = fetchFromDb(givenDate);
cacheData(giveDate, bool);
return bool;
}
public boolean checkCache(LocalDate giveDate) {
return cacheManager.getData(givenDate);
}
public boolean fetchFromDb(LocalDate givenDate) {
//return the data from database
}
public void cacheData(LocalDate givenDate, boolean bool) {
cacheManager.addToCache(givenDate, bool);
}
}
You can use Mockito.spy() for this kind of test. In this case you should spy your AllMarket instance and stub fetchFromDb. At the end you can Mockito.verify that fetchFromDb was called exactly once. It will look something like this:
AllMarket spy = spy(allMarket);
when(spy.fetchFromDb(givenDate)).thenReturn(true); //you have boolean as a return type
...
verify(spy, times(1)).fetchFromDb(givenDate);
For more information, you can see Official Mockito doc
Maybe mockito argument captor could asist you. It lets you to capture method input and how many times method was called, also may other functions. Please check https://www.baeldung.com/mockito-annotations.

golang singletons in beego

I'm trying out both Golang and Beego. I come from a Java/Spring background and I'm having a slightly difficult time implementing a singleton pattern for a webapp I'm developing. I have a controller (which I want to be a singleton) and I have a service within my controller (which I also want to be a singleton). I thought if I made my service a pointer, then I'd always use the same address (a singleton). This is not proving true.
My route looks like this
beego.Router("/", &controllers.SessionController{}, "get:Login")
My SessionController looks like this
type SessionController struct {
baseController
userService *services.UserService
}
func (this *SessionController) Prepare() {
this.baseController.Prepare()
if this.userService == nil {
beego.Info("user service was nil")
this.userService = factories.NewUserService()
}
}
My logs always show that the user service is nil upon each request. How can I get a single instance of my controller with a single (initialized only once) instance of my user service?
Make the user Service a singleton:
var globalUserService = factories.NewUserService()
type SessionController struct {
baseController
userService *services.UserService
}
func (this *SessionController) Prepare() {
this.baseController.Prepare()
if this.userService == nil {
beego.Info("user service was nil")
this.userService = globalUserService
}
}
1 of the creators of the Beego framework has mentioned to me that the framework creates a new instance of a controller per request, so it's not really possible to create a singleton :(
Here is everything you need to know about creating singleton in Golang
Singleton Pattern in Go
var instance *singleton
func GetInstance() *singleton {
if instance == nil {
instance = &singleton{} // <--- NOT THREAD SAFE
}
return instance
}
But that is not THREAD SAFE , you will need to use the Sync once
Example :-
import (
"sync"
)
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}

Resources