Golang service/daos implementation - go

Coming from a Java background, I have some questions on how things are typically done in Golang. I am specifically talking about services and dao's/repositories.
In java, I would use dependency injection (probably as singleton/application-scoped), and have a Service injected into my rest endpoint / resource.
To give a bit more context. Imagine the following Golang code:
func main() {
http.ListenAndServe("localhost:8080", nil)
}
func init() {
r := httptreemux.New()
api := r.NewGroup("/api/v1")
api.GET("/blogs", GetAllBlogs)
http.Handle("/", r)
}
Copied this directly from my code, main and init are split because google app engine.
So for now I have one handler. In that handler, I expect to interact with a BlogService.
The question is, where, and in what scope should I instantiate a BlogService struct and a dao like datastructure?
Should I do it everytime the handler is triggered, or make it constant/global?
For completeness, here is the handler and blogService:
// GetAllBlogs Retrieves all blogs from GCloud datastore
func GetAllBlogs(w http.ResponseWriter, req *http.Request, params map[string]string) {
c := appengine.NewContext(req)
// need a reference to Blog Service at this point, where to instantiate?
}
type blogService struct{}
// Blog contains the content and meta data for a blog post.
type Blog struct {...}
// newBlogService constructs a new service to operate on Blogs.
func newBlogService() *blogService {
return &blogService{}
}
func (s *blogService) ListBlogs(ctx context.Context) ([]*Blog, error) {
// Do some dao-ey / repository things, where to instantiate BlogDao?
}

You can use context.Context to pass request scoped values into your handlers (available in Go 1.7) , if you build all your required dependencies during the request/response cycle (which you should to avoid race conditions, except for dependencies that manage concurrency on their own like sql.DB). Put all your services into a single container for instance, then query the context for that value :
container := request.Context.Value("container").(*Container)
blogs,err := container.GetBlogService().ListBlogs()
read the following material :
https://golang.org/pkg/context/
https://golang.org/pkg/net/http/#Request.Context

Related

How do I improve the testability of go library methods

I'm writing some code that uses a library called Vault. In this library we have a Client. My code makes use of this Client but I want to be able to easily test the code that uses it. I use only a couple methods from the library so I ended up creating an interface:
type VaultClient interface {
Logical() *api.Logical
SetToken(v string)
NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
}
Now if my code is pointed at this interface everything is easily testable.. Except let's look at the Logical() method. It returns a struct here. My issue is that this Logical struct also has methods on it that allow you to Read, Write, ex:
func (c *Logical) Read(path string) (*Secret, error) {
return c.ReadWithData(path, nil)
}
and these are being used in my project as well to do something like:
{{ VaultClient defined above }}.Logical().Write("something", something)
Here is the issue. The Logical returned from the call to .Logical() has a .Write and .Read method that I can't reach to mock. I don't want all the logic within those methods to run in my tests.
Ideally I'd like to be able to do something similar to what I did above and create an interface for Logical as well. I'm relatively new to Golang, but I'm struggling with the best approach here. From what I can tell that's not possible. Embedding doesn't work like inheritance so it seems like I have to return a Logical. That leaves my code unable to be tested as simply as I would like because all the logic within a Logical's methods can't be mocked.
I'm sort of at a loss here. I have scoured Google for an answer to this but nobody ever talks about this scenario. They only go as far as I went with the initial interface for the client.
Is this a common scenario? Other libraries I've used don't return structs like Logical. Instead they typically just return a bland struct that holds data and has no methods.
package usecasevaultclient
// usecase.go
type VaultClient interface {
Logical() *api.Logical
SetToken(v string)
NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
}
type vaultClient struct {
repo RepoVaultClient
}
// create new injection
func NewVaultClient(repo RepoVaultClient) VaultClient {
return &vaultClient{repo}
}
func(u *vaultClient) Logical() *api.Logical {
// do your logic and call the repo of
u.repo.ReadData()
u.repo.WriteData()
}
func(u *vaultClient) SetToken(v string) {}
func(u *vaultClient) NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
// interfaces.go
type RepoVaultClient interface {
ReadData() error
WriteData() error
}
// repo_vaultclient_mock.go
import "github.com/stretchr/testify/mock"
type MockRepoVaultClient struct {
mock.Mock
}
func (m *MockRepoVaultClient) ReadData() error {
args := m.Called()
return args.Error(0)
}
func (m *MockRepoVaultClient) WriteData() error {
args := m.Called()
return args.Error(0)
}
// vaultClient_test.go
func TestLogicalShouldBeSuccess(t *testing.T) {
mockRepoVaultClient = &MockRepoVaultClient{}
useCase := NewVaultClient(mockRepoVaultClient)
mockRepoVaultClient.On("ReadData").Return(nil)
mockRepoVaultClient.On("WriteData").Return(nil)
// your logics gonna make this response as actual what u implemented
response := useCase.Logical()
assert.Equal(t, expected, response)
}
if you want to test the interface of Logical you need to mock the ReadData and WriteData , with testify/mock so u can defined the respond of return of those methods and you can compare it after you called the new injection of your interface

Insert data with Gorm with reflect

I'm creating a basic REST service. My intent is to write the logic for the resources as abstractly as possible. What I mean is if I have already created a CRUD logic for endpoint /devices for example, then when I need a new resource endpoint like /cars, I should not be repeating myself over the CRUD procedures.
In another language like Python, classes and methods are first class objects and that can be stored in a list or dictionary (map) and then instantiated as needed. In Go it doesn't seem as easy. I tried to use the reflect package.
First I create a TypeRegistry according to this.
var TypeRegistry = make(map[string]reflect.Type)
TypeRegistry["devices"] = reflect.TypeOf(models.Device{}) // models.Device{} is the Gorm SQL table model
Then I have handler creator which is intended to handle the creation of all types of resources like this (error handling redacted):
func CreateOneHandler(typeString string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
jsn, _ = ioutil.ReadAll(r.Body)
jsonBytes, _ := datamapper.CreateOne(typeString, jsn)
w.Write(jsonBytes)
}
}
I'm using Chi, so I bind the handlers like this:
func addRoute(r chi.Router, endpoint string, typeString string) {
r.Route("/"+endpoint, func(r chi.Router) {
typeString := endpoint
r.Post("/", CreateOneHandler(typeString))
})
}
The idea is to, after defining the Gorm models, simply add routes by calling it repeatedly, addRoute(r, "devices"); addRoute(r, "cars") for a consistent REST interface across multiple models.
Now within CreateOne() I want to insert something into the table:
func CreateOne(typeString string, json []byte) ([]byte, error) {
modelType := typeregistry.TypeRegistry[typeString]
value := reflect.New(modelType)
db.Create(modelPtr.Elem()) // ==> Now this doesn't work
}
How do I make it work? Gorm said "create failed no such table: value". Because a reflect value or reflect type isn't the same as if I were just to instantiate objects the regular way. How do I make it work?
(A side note: given the static nature of the type switch and type assertions, I am already compromising some of my designs which would probably be possible in a language like Python. It seems to me like it's unavoidable to litter code with type switches which tried to check whether it is a device, car or any number of new models explicitly. In a regular object-oriented language maybe this would be simple polymorphic method call. Any pointer to better design would be appreciated as well.)

What is the best way to have dependency injection in Golang

I'm a beginner in Golang and I'm working on a small library which need to get a DB connection at some point in the code for différent sub package / method call. I'm just wondering how I can manage this ?
Example, If I manage to have a webserver, it works with handler, so how can I get this connection inside this function ?
It could be used with another process, simple method call or MVC model ?
I don't want to use global because for me it's a bad practice except if it's very exceptional way (or tricky somehow).
I read a lot of write in different website, but still, I'm asking and learning from different opinion and experiences.
Thanks for your time !
Create a struct that represent the resource​, let's call Cart. Add get and post methods to this struct. These methods should be http handlers. In main create an instance of the struct with db interface. And in the route call Cart.get. Now in get method you have access to the db interface.
Not a working example, just to get the idea of injecting for testing.
type storage interface {
PrepareContext(context.Context, string) (*sql.Stmt, error)
}
func main() {
db, _ := sql.Open("mysql", `queryString`)
http.HandleFunc("/", Cart{db}.get)
http.ListenAndServe(":8080", nil)
}
type Cart struct {
storage
}
func (crt Cart) get(w http.ResponseWriter, r *http.Request) {
q, _ := crt.PrepareContext(context.Background(), `select *`)
fmt.Println(q.Exec())
}
/////////Test
type testDB struct{}
func (c testDB) PrepareContext(context.Context, string) (*sql.Stmt, error) {
return nil, nil
}
func TestGet(t *testing.T) {
db := testDB{}
_ = Cart{db}
//http test here
}
I would suggest Dargo which is an injection engine in the style of Java CDI and/or JSR-330. It uses struct annotations and Injection is performed using reflection or using creator functions. It supports different lifecycles for services including Singleton (created exactly once, lazily), PerLookup (created every time injected or looked up), Immediate (created exactly once, eagerly) and DargoContext (tied to the lifecycle of a context.Context)
You can also try Hiboot which is a web/cli application framework that support dependency injection out of box.
Docs
// HelloService is a simple service interface, with interface, we can mock a fake service in unit test
type HelloService interface {
SayHello(name string) string
}
type helloServiceImpl struct {
}
func init() {
// Register Rest Controller through constructor newHelloController
// Register Service through constructor newHelloService
app.Register(newHelloController, newHelloService)
}
// please note that the return type name of the constructor HelloService,
// hiboot will instantiate a instance named helloService for dependency injection
func newHelloService() HelloService {
return &helloServiceImpl{}
}
// SayHello is a service method implementation
func (s *helloServiceImpl) SayHello(name string) string {
return "Hello" + name
}
// PATH: /login
type helloController struct {
web.Controller
helloService HelloService
}
// newHelloController inject helloService through the argument helloService HelloService on constructor
func newHelloController(helloService HelloService) *helloController {
return &helloController{
helloService: helloService,
}
}
// Get /
// The first word of method name is the http method GET
func (c *helloController) Get(name string) string {
return c.helloService.SayHello(name)
}
I would suggest giving a try to https://github.com/facebookgo/inject. It allows to define an object graph and specify dependencies with struct annotations. Injection is performed using reflection.
For an IoC container, you can try this package:
https://github.com/golobby/container
Example of singleton binding:
container.Singleton(func() Database {
return &MySQL{}
})
Example of resolving:
var db Database
container.Make(&db)
As you can see it's so easy to work with.

Dependency injection with http Handler in Go

I am trying to wrap my head around dependency injection in Go, but really stuck here. Here's a (drastically simplified) app which should serve as an example:
package main
import (
"net/http"
"github.com/gorilla/mux"
)
func main() {
mux := mux.NewRouter()
mux.Handle("/", myHandler()).Methods("GET")
http.ListenAndServe(":9000", mux)
}
type myObject interface {
Start()
}
type Object struct {
}
func (o *Object) Start() {
// Something wild here, for example sending out an email,
// query an external DB or something similar..
}
func myHandler() http.Handler {
// Inject myObject-like struct somewhere here?
o := Object{}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
o.Start()
w.Write([]byte("Started Object"))
})
}
I have a problem with testing the Object struct. What I usually do is create an interface which can be used in testing by setting up a test struct. For instance, if I had a DB connection handler, in testing I can create a mock which satisfies the handler interface and pass this to the "myHandler" call as a parmeter.
Unfortunately this only works if the struct is already instantiated when the "mux.Handle" call is made. I simply don't see any simple way to test the myHandler function with an Object struct which can be injected in tests, since it will be created after the handler gets called.
Any hints or ideas on how to get this done? Maybe I have to rethink my testing approach, but I would really like to unit-test the Object struct, but also test the http handler separately (as this handler may perform more tasks than just creating the Object).

Defining an interface method with interface return type

TLDR Here is a playground that demonstrates the issue if you try to run it: https://play.golang.org/p/myQtUVg1iq
I am making a REST API and have many types of resources that can be retrieved via a GET request
GET http://localhost/api/users
GET http://localhost/api/groups
I have a models package which abstracts how the different resources are implemented:
func(m *UserManager) Get() []Users {
// Internal logic, assume returns correct results
}
func(m *GroupManager) Get() []Groups {
// Internal logic, assume returns correct results
}
A routes file setups all the routes and handlers:
users := models.UserManager{}
groups := models.GroupManager{}
func GetUsersHandler (w http.ResponseWriter, r *http.Request) {
users := users.Get()
// Implementation details, writing to w as JSON
}
func GetGroupsHandler (w http.ResponseWriter, r *http.Request) {
groups := groups.Get()
// Implementation details, writing to w as JSON
}
func registerRoutes(r *mux.Router) {
r.handleFunc("/api/users", GetUsersHandler).Method("GET")
r.handleFunc("/api/groups", GetGroupsHandler).Method("GET")
}
I am trying to make this more generic by creating an interface and then only needing a single GetHandler. Something like this:
type Getter interface {
Get() []interface{}
}
func GetHandler(g Getter) {
return func(w http.ResponseWriter, r *http.Request) {
results := g.Get()
// Implementation details, writing to w as JSON
}
}
func registerRoutes(r *mux.Router) {
r.handleFunc("/api/users", GetHandler(&users)).Method("GET")
r.handleFunc("/api/groups", GetHandler(&groups)).Method("GET")
}
This is really close to working, the only problem is the return type from the models is a specific object type, but the interface just uses the interface return type. Is there any way to solve this without making the models return []interface{}?
https://play.golang.org/p/myQtUVg1iq
Try not to approach the problem like you would other OOP languages. You can't have covariant containers in Go, so you either have to use an empty interface{}, or you have to structure your program differently.
If your Get methods are different and you want to group types in an interface, use another method (sometimes we even have noop methods just for interfaces), or just pass in users or groups as an interface{}. You'll need to do a type switch or assertion at some point in the call chain anyway, and once you know what type it is you can handle it accordingly.
It's hard to tell without more code, but in this case, the easiest path may just be to have each type be an http.Handler itself, and it can dispatch accordingly.
I ended up avoiding this problem entirely and instead of trying to reduce the amount of code I am using the new go generate feature in Go 1.4 to create the code that is necessary for each resource.

Resources