Microservices in Go: Architecture and Practice from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to Microservices in Go



Microservice architecture has become the de facto standard for building modern distributed systems. The Go language (Golang), with its lightweight goroutines, high performance, and ease of deployment, is ideally suited for implementing microservices. In this article, we will break down microservice architecture in Go from concept to practical implementation with code examples.



Go offers built-in concurrency support, fast startup, and small binary sizes — all of which are critically important for microservices. We will look at how to design a service, implement a REST API, add middleware, and prepare the application for containerization.



Microservice Architecture in Go



1. Project Structure



Proper code organization is the foundation of a maintainable microservice. Recommended structure:



myservice/├── cmd/│   └── server/│       └── main.go          # Entry point├── internal/│   ├── handler/             # HTTP handlers│   ├── service/             # Business logic│   ├── repository/          # Data access│   └── middleware/          # Middleware handlers├── pkg/│   └── models/              # Common data models├── config/│   └── config.go            # Configuration├── go.mod└── Dockerfile


This structure follows Clean Architecture principles: handler → service → repository. This allows each layer to be tested independently with ease.



2. Configuration and Startup



Let's start with a simple HTTP server using the standard net/http library:



// cmd/server/main.gopackage main

import ( "fmt" "log" "net/http" "os")

func main() { port := os.Getenv("PORT") if port == "" { port = "8080" }

http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, `{"status": "ok"}`) })

log.Printf("Server starting on :%s", port) log.Fatal(http.ListenAndServe(":"+port, nil))}


This is a minimal microservice. For production, use a router with middleware support, such as gorilla/mux or chi.



Practical Microservice Implementation



3. REST API with gorilla/mux



Let's install gorilla/mux and implement CRUD for a "User" entity:



// go.modmodule github.com/youruser/userservice

go 1.21

require github.com/gorilla/mux v1.8.1


// internal/handler/user.gopackage handler

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

type User struct { ID string `json:"id"` Name string `json:"name"` Age int `json:"age"`}

var users = []User{ {ID: "1", Name: "Alice", Age: 30},}

func GetUsers(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users)}

func CreateUser(w http.ResponseWriter, r *http.Request) { var newUser User if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } users = append(users, newUser) w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(newUser)}


// cmd/server/main.go (continued)package main

import ( "log" "net/http" "github.com/gorilla/mux" "yourproject/internal/handler")

func main() { r := mux.NewRouter() r.HandleFunc("/users", handler.GetUsers).Methods("GET") r.HandleFunc("/users", handler.CreateUser).Methods("POST")

log.Println("Server started on :8080") log.Fatal(http.ListenAndServe(":8080", r))}


4. Middleware: Logging and Authentication



Middleware is an integral part of microservices.

Blogs

Book Recommendations