DEV Community

Aman Bhardwaj
Aman Bhardwaj

Posted on

Building a Golang HTTP Server: From Hello World to Dependency Injection

GoLang

Introduction:

In this article, we'll explore the process of building an HTTP server using Golang, from the initial setup of a blank project to implementing routes and utilizing dependency injection for a cleaner and more maintainable codebase.

Setting Up the Project:

To kick things off, let's start by creating a new Golang project in Visual Studio Code. Navigate to a blank folder, open VS Code, and create a file named "main.go." Begin with the standard package declaration and a simple "Hello, World!" output using the fmt package.

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}
Enter fullscreen mode Exit fullscreen mode

Spinning Up the Basic HTTP Server:

Moving on, we'll evolve our project into an HTTP server. Golang provides a straightforward way to accomplish this, as demonstrated by the following code snippet:

package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Hello, Go!")
    })

    http.ListenAndServe(":3000", nil)
}
Enter fullscreen mode Exit fullscreen mode

This basic setup responds with "Hello, Go!" when accessing the root URL. However, the absence of defined routes results in a 404 page.

Cleaning Up with Gorilla Mux:

To enhance the structure of our server, we'll employ the Gorilla Mux package for handling routes. First, initialize the Go module and add the Gorilla Mux package.

go mod init github.com/your-username/your-project
go get github.com/gorilla/mux
Enter fullscreen mode Exit fullscreen mode
package main

import (
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

func main() {
    router := mux.NewRouter()

    router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Hello, Go!")
    })

    http.Handle("/", router)
    http.ListenAndServe(":3000", nil)
}
Enter fullscreen mode Exit fullscreen mode

Implementing Dependency Injection:

To further enhance our project's structure, we'll implement dependency injection by creating a new file named "api.go." This new file introduces a more organized approach to managing the server instance.

package main

import (
    "net/http"
    "github.com/gorilla/mux"
)

// API struct represents the API server.
type APIServer struct {
    address string
}

// NewAPI initializes a new APIServer instance.
func NewAPIServer(address string) *APIServer{
    return &APIServer{
        address: address,
    }
}

// Run starts the API server.
func (a *APIServer) Run() error {
    router := mux.NewRouter()
    router.HandleFunc("/hello", a.handleGreet)

    fmt.Printf("Server starting on address %s", a.addr)
    return http.ListenAndServe(a.address, router)
}
Enter fullscreen mode Exit fullscreen mode

With this approach, we have a more modular and organized project structure.
Now let's embed our handler into the API to handle our "/hello" route.
Let's create a new file named "routes.go"

func (a *APIServer) handleGreet(w http.ResponseWriter, r *http.Request) {
   w.Write([]byte("Method not supported"))
   return
}
Enter fullscreen mode Exit fullscreen mode

The main.go file now looks cleaner:

package main

func main() {
    api := NewAPIServer(":3000")

    if err := api.Run(); err != nil {
        fmt.Println("Error starting the server:", err)
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion:

In this article, we've progressed from a basic "Hello, World!" program to building a more organized Golang HTTP server. By incorporating Gorilla Mux for routing and implementing dependency injection, our project becomes scalable, modular, and easier to maintain.
This was a mere glimpse of what we did in this Udemy course of mine:
REST API using GoLang, PostgreSQL, Keycloak, Docker
I will see you in the next article. Until then, scatter.

Now you know where to find me:
LinkedIn
YouTube
Github
Udemy

Top comments (0)