Go web application with a mock user repository
To really understand the blog post, I recommend looking at its example project (https://github.com/benbjohnson/wtf - see also http branch).

Ben Johnsons posted another post detailing its steps: https://medium.com/wtf-dial/wtf-dial-domain-model-9655cd523182).

Regarding the organization of your code, it would be like this:

project.go // the exported interfaces
mock/      // the mock implementations
http/      // http handler/server
mysql/     // the mysql implementations
cmd/       // the 'glue'


A major point is that you can only import parent (sub)packages.
For instance your http subpackage can not depend on the mysql subpackage (http should only depend on the interfaces defined in project.go - project.UserService for instance).

The only exception to this rule is your main.go (or your tests).
For instance, you import project/http and project/mysql and connect them :

Since the mysql.UserService struct implements the project.UserService interface it is transparent for the http package which expects a project.UserService interface



project.go

take a look at https://github.com/benbjohnson/wtf/blob/http/wtf.go

package project

type UserID int

type User struct {
    Name string
}

type UserService interface {
    GetByID(UserID) (*User, error)
}

// HTTPService is similar




mock/user.go

take a look at https://github.com/benbjohnson/wtf/blob/http/mock/mock.go

package mock

import (
    "your/project"
)

type UserService struct {
    GetByIDFn      func(id project.UserID) *project.User, error
    GetByIDInvoked bool
}

func (s *UserService) GetByID(id project.UserID) (*project.User, error) {
    s.GetByIDInvoked = true
    return s.GetByIDFn(id)
}




mysql/user.go

Your actual implementation with a MySQL database for instance (adapt to your own user backend)



http/*.go

take a look at https://github.com/benbjohnson/wtf/tree/6d855c355488361b22b1a5ba13d9453e39141292/http

package http

import (
    "your/project"
    "net/http"
)

type HTTPService struct {
    // Here you embed some UserService Interface
    UserService project.UserService
}

func (h *HTTPService) HandleHTTP(w http.ResponseWriter, r *http.Request) {
    // Use the UserService Interface (don't care if it's mock or real)
    h.UserService.GetByID(...)
    // write response
}




cmd/mocked/main.go

Glue everything (be careful of import names conflicts!):

package main

import (
    "your/project/http"
    nethttp "net/http"
)

func main(){
    server := http.HTTPService{
        UserService: mock.UserService{},
    }

    nethttp.ListenAndServe(":8888", server)
}