DEV Community

Cover image for Dependency Injection like a Pro in Golang
Dsysd Dev
Dsysd Dev

Posted on

Dependency Injection like a Pro in Golang

Are you ever confused about dependency injection ? What if i tell you that it's the simplest topic ever! It's just about passing values to a function !!

If you prefer the video version

https://www.youtube.com/watch?v=AJ6uz9mlFOA

Dependency Injection is just a fancy way of saying "passing stuff into a function." It's about giving a function or object the things it needs to work.

It's like baking pizza. You don't bake the pizza at home; you call a pizza place and tell them what you want. The pizza delivery is like a function that takes your order (dependencies) and delivers the result (pizza).

func OrderPizza() {
    oven := NewOven()
    pizza := oven.BakePizza()
    // ...
}
Enter fullscreen mode Exit fullscreen mode

This function creates its own dependencies (the oven) instead of having them provided.

func OrderPizza(oven Oven) {
    pizza := oven.BakePizza()
    // ...
}
Enter fullscreen mode Exit fullscreen mode

The function is more flexible because you can now choose which oven to use (e.g., regular oven or wood-fired oven).

Dependency Injection is widely used in Go, especially in building HTTP servers. Explain that you can pass different routers, middleware, and database connections to the server as dependencies.

package main

import (
 "fmt"
 "net/http"
)

// Router defines the interface for a router.
type Router interface {
 HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
}

// MyRouter is an example implementation of the Router interface.
type MyRouter struct{}

func (r *MyRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
 http.HandleFunc(pattern, handler)
}

// LoggerMiddleware is an example middleware.
func LoggerMiddleware(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  fmt.Println("Logging:", r.URL.Path)
  next.ServeHTTP(w, r)
 })
}

func main() {
 // Create a router instance
 router := &MyRouter{}

 // Attach middleware
 http.Handle("/", LoggerMiddleware(router))

 // Define routes
 router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Welcome to our website!")
 })

 router.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "About Us")
 })

 router.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Contact Us")
 })

 // Start the server
 fmt.Println("Server is listening on :8080")
 http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

In this example:

We define a Router interface that has a HandleFunc method, which mimics the behavior of Go's http.HandleFunc.

MyRouter is an implementation of the Router interface.
We create a LoggerMiddleware function, which is a middleware that logs incoming requests.

In the main function, we create an instance of MyRouter.
We attach the LoggerMiddleware to the router to log requests.

We define routes using the HandleFunc method provided by our router, which is the equivalent of http.HandleFunc.
Finally, we start the server using http.ListenAndServe.

This example demonstrates how you can use dependency injection to pass in routers and middleware to create a flexible and modular web server in Go.

You can easily swap out different routers or middleware components to customize your server's behavior.

Claps Please!

If you found this article helpful I would appreciate some claps 👏👏👏👏, it motivates me to write more such useful articles in the future.

Follow for regular awesome content and insights.

Subscribe to my Youtube channel

Subscribe to my youtube channel if you are on the lookout for more such awesome content in video format.

https://www.youtube.com/@dsysd-dev

Follow me on twitter 🐥

Join me on Twitter for a daily dose of knowledge, fascinating trivia, and valuable insights. Let's embark on a journey of continuous learning and discovery together! Follow me to stay inspired and informed. 🚀

https://twitter.com/dsysd_dev

Subscribe to my Newsletter

If you like my content, then consider subscribing to my free newsletter, to get exclusive, educational, technical, interesting and career related content directly delivered to your inbox

https://dsysd.beehiiv.com/subscribe

Important Links

Thanks for reading the post, be sure to follow the links below for even more awesome content in the future.

Twitter: https://twitter.com/dsysd_dev
Youtube: https://www.youtube.com/@dsysd-dev
Github: https://github.com/dsysd-dev
Medium: https://medium.com/@dsysd-dev
Email: dsysd.mail@gmail.com
Telegram 📚: https://t.me/dsysd_dev_channel
Linkedin: https://www.linkedin.com/in/dsysd-dev/
Newsletter: https://dsysd.beehiiv.com/subscribe
Gumroad: https://dsysd.gumroad.com/
Dev.to: https://dev.to/dsysd_dev/

Top comments (3)

Collapse
 
yury_hurski profile image
Yury_Hurski • Edited

The last code sample is not working at all, and the intention to write an http middleware that way (w/o using a custom instance of ServeMux for routes) isn't clear to me, so here's a least effort working version of the sample:

package main

import (
    "fmt"
    "net/http"
)

// MyRouter is an example implementation of the Router interface.
type MyRouter struct{}

func (MyRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
    http.HandleFunc(pattern, handler)
}

func (MyRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    http.DefaultServeMux.ServeHTTP(w, r)
}

// LoggerMiddleware is an example middleware.
func LoggerMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Logging:", r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

func main() {
    // Create a router instance
    router := MyRouter{}

    // Define routes
    router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Welcome to our website!")
    })

    router.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "About Us")
    })

    router.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Contact Us")
    })

    // Start the server
    fmt.Println("Server is listening on :8080")
    http.ListenAndServe(":8080", LoggerMiddleware(router))
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
dsysd_dev profile image
Dsysd Dev

thanks, i will look into it

Collapse
 
coosir profile image
coosir

example code is not runnable, obvious mistakes