Dependency Injection

Dependency injection (or DI in short)

There are many situations in which you have to inject dependencies to your class(struct), functions, and etc.

In Java, Spring Framework is well known for its container-based dependency injection.

Go is a procedural language(they say), and here are some simple ways to inject dependencies in my opinion.

Pass struct variable as parameters of constructors

type UserHandler struct {
    userService UserService
}

type NewUserHandler(userService UserService) *UserHandler {
    return &UserHandler{userService: userService}
}

func (h *UserHandler) FindUsers(w http.ResponseWriter, r *http.Request) {
    // ...
    users, err := h.userService.FindAll()
    if err != nil {
        // ...
    }
    // ...
}

// ...
func addRoutes(...) {
    // ...
    userService := NewUserService(userRepository)
    userHandler := NewUserHandler(userService)

    // register userHandler to your routes...
}

Pass function pointers as parameters

Since function pointers are also allowed, you can inject function dependencies via parameters.

type UserRepository struct{}

func (r *UserRepository) FindAll() []string {
    return []string{"John", "Jane", "Alice"}
}

type UserService struct {
    UserRepo *UserRepository
}

func (s *UserService) FindAllUsers(findFunc func() []string) {
    users := findFunc()
    // ...
}

func main() {
    userRepo := &UserRepository{}
    userService := &UserService{UserRepo: userRepo}

    userService.FindAllUsers(userRepo.FindAll)
}

DI libraries

If you really want to use a "library" to inject dependencies, here are some famous libraries.

But I don't really recommend using any. Once you introduce a third party DI container to your application, you lose simplicity and explicitness, which are considered core principles of Go.

Last updated