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!") }
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) }
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
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) }
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) }
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 }
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) } }
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
