Skip to content

Archive

Golang

56 articles
Go 01 Sep 2026 7 min read

Bounded Concurrency in Go with a Worker Pool

Goroutines are cheap, but the resources they call are often not. Starting one goroutine for every item in a large batch can overwhelm a database connection pool, trigger API rate limits, exhaust file descriptors, or create avoidable memory pressure. Bounded concurrency solves this by allowing only a fixed number of operations to run at the same time. A worker pool is one of the simplest standard-library patterns for implementing that limit in Go.

Go 01 Sep 2026 6 min read

Atomic File Writes in Go: Prevent Partial and Corrupted Files

Writing a file with os.WriteFile is simple, but it is not always the safest choice for configuration files, generated metadata, caches, state files, or other data that must never be left half-written. If a process crashes or the machine loses power while a file is being replaced, readers may observe incomplete content. A common way to reduce this risk is an atomic file write: write the new content to a temporary file first, then replace the destination with a rename.

Cloud Computing 06 Sep 2025 3 min read

Reverse Proxy with Nginx and Go for Microservices

As an application grows, splitting it into smaller services can make independent deployment and scaling easier. For example: Product service on port 8080 Blog service on port 8081 Users should not need to know those internal ports. An Nginx reverse proxy can expose both services under one domain and route requests by URL path. 1. Configure the Nginx Reverse Proxy Create a site configuration: sudo nano /etc/nginx/sites-available/yourdomain.com Add:

Go Updated 02 Sep 2025 2 min read

Working with Time in Go Without the Headaches

Time handling looks simple until time zones, parsing, durations, and scheduling enter the picture. Go’s standard time package covers the common cases without requiring third-party libraries. Current Time currentTime := time.Now() fmt.Println("Now:", currentTime) time.Now() returns the current local time according to the process environment.

Cloud Computing Updated 02 Sep 2025 2 min read

Using Nginx as a Reverse Proxy for a Go Application

A Go web application often listens directly on an application port such as :8080. If you want users to access it through a normal domain on port 80 or 443, you can place Nginx in front of it as a reverse proxy. Using Nginx in front of a Go service provides several benefits: Client requests reach Nginx before being forwarded to the Go application. TLS termination can be handled at the proxy layer. Multiple application instances can be load balanced. Static assets can be served separately when that architecture makes sense. This guide shows a basic setup.

Go Updated 02 Sep 2025 2 min read

Structs in Go: A Practical Guide with Examples

A struct groups related fields into a single Go type. Structs are the standard way to model domain entities, configuration, request data, records, and many other compound values. Define a Struct type Person struct { Name string Age int Address string } p := Person{Name: "Alice", Age: 30, Address: "123 Main St"} fmt.Println(p.Name, p.Age, p.Address) Using field names in composite literals is usually clearer and more resilient than relying on field order.

Go Updated 02 Sep 2025 3 min read

Several Ways to Handle Optional Parameters in Go

Go deliberately does not support optional or default function parameters like some other languages. Function signatures are explicit, which keeps call sites and APIs predictable. When an API genuinely needs optional configuration, Go developers usually choose one of a few established patterns. 1. Variadic Parameters A variadic parameter (...) is useful when the optional part is simply zero or more values of the same type: func greet(message string, names ...string) { for _, name := range names { fmt.Printf("%s, %s!\n", message, name) } } func main() { greet("Hello") greet("Hello", "Alice", "Bob", "Charlie") } message is required, while names may contain zero, one, or many values.

Go Updated 02 Sep 2025 3 min read

Pretty-Printing JSON in Go with MarshalIndent

Compact JSON is efficient for transport, but long documents can be difficult to inspect when everything appears on one line. Go’s standard encoding/json package includes json.MarshalIndent for producing human-readable JSON with line breaks and indentation. Pretty-printed JSON is useful for debugging, generated configuration, logs intended for people, and command-line output. 1. Use json.MarshalIndent package main import ( "encoding/json" "fmt" ) func main() { data := map[string]any{ "name": "Alice", "age": 30, "address": map[string]string{ "street": "123 Main St", "city": "Wonderland", }, "hobbies": []string{"reading", "hiking", "coding"}, } prettyJSON, err := json.MarshalIndent(data, "", " ") if err != nil { fmt.Println("Error:", err) return } fmt.Println(string(prettyJSON)) } MarshalIndent accepts three arguments:

Go Updated 02 Sep 2025 2 min read

Practical Ways to Combine Slices in Go

Combining slices is common when data comes from several sources or processing stages. In Go, the standard approach is append, optionally with preallocated capacity when the final size is known. 1. Combine Slices with append package main import "fmt" func main() { slice1 := []int{1, 2, 3} slice2 := []int{4, 5, 6} slice3 := []int{7, 8, 9} combined := append(slice1, slice2...) combined = append(combined, slice3...) fmt.Println(combined) } Output:

Go Updated 02 Sep 2025 2 min read

Maps in Go: A Practical Guide with Examples

A Go map stores key-value pairs and gives you fast lookup by key. It is similar to a dictionary or hash map in other languages and is one of Go’s most useful built-in data structures. Creating a Map Using make: personAge := make(map[string]int) personAge["Alice"] = 30 personAge["Bob"] = 25 fmt.Println(personAge) Using a map literal:

Go Updated 02 Sep 2025 3 min read

Manage Goroutine Work Queues Efficiently in Go

Goroutines are one of Go’s defining features. They make concurrent work inexpensive to start, but creating an uncontrolled number of goroutines can still overwhelm memory, downstream services, file descriptors, or database connections. A common solution is a bounded worker pool: tasks are placed on a channel and a fixed number of goroutines consume them. Why Use a Queue? A controlled work queue helps you: limit the number of active workers; apply backpressure when work arrives faster than it can be processed; centralize task scheduling; shut down cleanly after queued work finishes. 1. A Basic Channel-Based Queue type Task struct { ID int } func worker(id int, tasks <-chan Task) { for task := range tasks { fmt.Printf("Worker %d processing task %d\n", id, task.ID) time.Sleep(time.Second) } } A channel can hold pending tasks while several workers read from it.

Go Updated 02 Sep 2025 2 min read

Loops in Go: A Practical Guide with Examples

Go has only one looping keyword: for. That can look unusual if you come from a language with separate for, while, and do-while constructs, but Go’s for is flexible enough to cover the common looping patterns. 1. Basic for Loop for i := 0; i < 5; i++ { fmt.Println(i) } This is similar to a traditional loop in C, Java, or JavaScript: initialize a counter, continue while the condition is true, and run the post statement after each iteration.

Go Updated 02 Sep 2025 4 min read

Learning Interfaces in Go: Concepts, Examples, and Best Practices

Interfaces are one of Go’s most important abstraction tools. An interface describes behavior as a set of method signatures. A concrete type satisfies an interface implicitly simply by implementing the required methods—there is no separate implements declaration. What Is an Interface? An interface is a set of methods. For example: type Speaker interface { Speak() string } type Person struct { Name string } func (p Person) Speak() string { return "Hello, my name is " + p.Name } Because Person has the required Speak() string method, it satisfies Speaker:

Go Updated 02 Sep 2025 2 min read

How to Safely Convert a String to an Integer in Go

Numbers often arrive as strings from command-line arguments, form input, files, environment variables, or APIs. Before performing arithmetic, convert the text with Go’s strconv package and handle invalid input explicitly. 1. Use strconv.Atoi() for int Atoi is the simplest choice when you want a base-10 int: package main import ( "fmt" "strconv" ) func main() { str := "123" num, err := strconv.Atoi(str) if err != nil { fmt.Println("Error:", err) return } fmt.Println("Number:", num) } Invalid input such as "12a" returns an error. Never assume external text is valid without checking it.

Go Updated 02 Sep 2025 2 min read

How to Get a Slice of Map Keys in Go

Go maps store key-value pairs, but many tasks only need the keys—for example, to sort them, display them, compare sets, or feed them into another operation. Map iteration is intentionally unordered, so extracting keys into a slice is also the first step when you need a deterministic order. 1. Collect All Keys with range func getMapKeys(m map[string]int) []string { keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } return keys } func main() { myMap := map[string]int{ "apple": 1, "banana": 2, "cherry": 3, } keys := getMapKeys(myMap) fmt.Println("Keys:", keys) } Preallocating the slice with capacity len(m) avoids unnecessary growth while keys are appended.

Go Updated 02 Sep 2025 2 min read

How to Create Enum-Like Types in Go

Go does not have a dedicated enum keyword like Java, C#, or TypeScript. Instead, enum-like values are usually modeled with a named type plus constants, often using iota to generate sequential values. 1. A Simple Enum-Like Constant Set with iota iota is a counter that starts at zero within a const block and increments for each constant specification: package main import "fmt" const ( Red = iota Green Blue ) func main() { fmt.Println("Red:", Red) fmt.Println("Green:", Green) fmt.Println("Blue:", Blue) } Output:

Go Updated 02 Sep 2025 2 min read

How to Check Whether a Map Contains a Key in Go

Go has a built-in idiom for checking whether a map contains a key. A map lookup can return both the stored value and a boolean indicating whether the key is present. Check a Key myMap := map[string]int{ "apple": 1, "banana": 2, "cherry": 3, } key := "banana" value, exists := myMap[key] if exists { fmt.Printf("Key '%s' exists with value %d\n", key, value) } else { fmt.Printf("Key '%s' does not exist\n", key) } The boolean is important because a missing key returns the value type’s zero value. Without the boolean, you cannot distinguish a missing key from a present key whose stored value happens to be zero.

Go Updated 02 Sep 2025 2 min read

How to Check Whether a File Exists in Go

Checking whether a file exists is a common task when working with configuration, local state, generated output, or other filesystem resources. Go’s os package provides the necessary APIs, but it is important to distinguish “does not exist” from other errors such as permission failures. 1. Check with os.Stat os.Stat returns file metadata when the path can be resolved: package main import ( "errors" "fmt" "os" ) func fileExists(filename string) (bool, error) { _, err := os.Stat(filename) if err == nil { return true, nil } if errors.Is(err, os.ErrNotExist) { return false, nil } return false, err } func main() { filename := "example.txt" exists, err := fileExists(filename) if err != nil { fmt.Println("Error:", err) return } if exists { fmt.Printf("File '%s' exists.\n", filename) } else { fmt.Printf("File '%s' does not exist.\n", filename) } } Returning an error prevents permission or I/O problems from being mistaken for a missing file.

Go Updated 07 Sep 2025 2 min read

Generate Random Strings in Go

Random strings are useful for temporary identifiers, test data, filenames, invitation codes, and security-sensitive tokens. Go offers different random-number sources, and choosing the correct one matters. 1. math/rand for Non-Security Uses For simulations, test fixtures, randomized UI behavior, or other cases where predictability is not a security problem, math/rand is appropriate. With modern Go, create an explicit generator when you need independent pseudo-random state: package main import ( "fmt" "math/rand" ) const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" func GenerateRandomString(r *rand.Rand, length int) string { result := make([]byte, length) for i := range result { result[i] = alphabet[r.Intn(len(alphabet))] } return string(result) } func main() { r := rand.New(rand.NewSource(42)) fmt.Println(GenerateRandomString(r, 10)) } A fixed seed is useful for reproducible tests. Do not use math/rand for secrets, session tokens, password-reset tokens, or other authentication material.

Go Updated 07 Sep 2025 2 min read

Efficient String Concatenation in Go

String concatenation appears everywhere in Go programs: generating text, building paths, formatting reports, or assembling protocol messages. The best technique depends on how many pieces you are joining and how the data is already structured. 1. The + Operator For a small, fixed number of strings, + is clear and perfectly reasonable: str1 := "Hello, " str2 := "world!" result := str1 + str2 Avoid repeatedly growing a string with + inside a large loop, because each result is a new immutable string and repeated copying can become expensive.

Go Updated 02 Sep 2025 2 min read

Easy Ways to Convert an Integer to a String in Go

Converting an integer to a string is common when building output, logs, identifiers, URLs, or serialized data. Go provides several standard-library options depending on whether you need a simple decimal conversion or more control over formatting. 1. strconv.Itoa() For an int in base 10, strconv.Itoa is usually the clearest choice: package main import ( "fmt" "strconv" ) func main() { num := 42 str := strconv.Itoa(num) fmt.Println("String value:", str) } Itoa is equivalent to formatting the int as a base-10 integer.

Go Updated 02 Sep 2025 2 min read

Deploy a Go Web Server with systemd on Linux

When developing a small Go web server, it is common to run it manually with go run main.go. The problem is that the process stops when the terminal closes, and it will not automatically return after a server reboot. A better production setup is to run the application as a systemd service. That gives you automatic startup, monitoring, service management, and optional restart behavior after failures. 1. Create a Simple Go Web Server Start with a minimal HTTP server:

Go Updated 02 Sep 2025 3 min read

Build a CRUD API with Go, Gin, MySQL, and GORM

This tutorial builds a small CRUD API with Go, the Gin web framework, MySQL, and GORM. It also uses godotenv for local development configuration. 1. Create the Project mkdir myapp cd myapp go mod init myapp 2. Install Dependencies go get github.com/gin-gonic/gin go get gorm.io/gorm go get gorm.io/driver/mysql go get github.com/joho/godotenv Run go mod tidy after adding your imports so the module file reflects the dependencies actually used by the application.

Go Updated 02 Sep 2025 3 min read

Arrays and Slices in Go: Add, Delete, Search, Update, Sort, and Filter

Go arrays and slices are straightforward once you understand their different roles. Arrays have a fixed length that is part of their type, while slices are flexible views over an underlying array and are the collection type used most often in application code. The following examples use a slice of structs: type Person struct { Name string Age int } people := []Person{ {Name: "Alice", Age: 30}, {Name: "Bob", Age: 25}, {Name: "John", Age: 20}, {Name: "Zara", Age: 35}, } 1. Add an Element Use append: