Skip to content

Topic archive

Go

Go, also known as Golang, is a statically typed programming language designed at Google for simplicity, fast compilation, efficient execution, and practical concurrency. It is widely used for backend services, cloud tooling, networking software, and command-line applications.

179 articles
Go 10 Sep 2026 6 min read

Process Go Slices in Batches with slices.Chunk

Batching a slice sounds simple until the loop starts collecting edge cases: the final batch may be short, an empty input needs sensible behavior, and careless subslicing can leave each batch with capacity to overwrite later elements. Go 1.23 added slices.Chunk, which handles that bookkeeping and exposes the batches as an iterator. If you already have the data in a slice and want to process consecutive groups without first building a [][]T, it’s a useful small tool.

Go 10 Sep 2026 7 min read

Preallocate Append Capacity in Go with slices.Grow

Sometimes you know a slice is about to receive several elements, even though you don’t have those elements yet. Repeated append calls will grow the slice automatically, but some of those appends may have to allocate a larger backing array and copy the existing elements. slices.Grow lets you reserve enough capacity for a known amount of upcoming growth. It doesn’t add placeholder elements and it doesn’t change the slice’s length. It simply returns a slice that has room for at least the requested number of additional elements.

Go 10 Sep 2026 5 min read

Iterate Go Slices in Reverse with slices.Backward

Walking a slice from the end used to mean writing the index loop yourself. That works, but the loop mechanics can distract from the actual job, especially when you need both the original index and the value. Since Go 1.23, slices.Backward provides that traversal directly. It returns an iterator. The slice stays in its original order, no reversed copy is created, and the indexes you receive are the real indexes from the source slice.

Go 10 Sep 2026 6 min read

Insert Iterator Pairs into Go Maps with maps.Insert

Sometimes a Go pipeline naturally produces key-value pairs, but the destination is a map you already have. Turning those pairs into a temporary map just to merge it adds a step that doesn’t help. Go 1.23 added maps.Insert for this case. It consumes an iter.Seq2[K, V] and writes each pair into an existing map. Existing keys are overwritten, unrelated entries stay in place, and the iterator can produce values lazily.

Go 10 Sep 2026 5 min read

Find Values and Insertion Points with slices.BinarySearch

When a Go slice is already sorted, scanning it from the beginning to find one value throws away useful information. slices.BinarySearch uses that ordering directly. It returns both an index and a found flag, and the index remains useful even when the target isn’t present. That second behavior is easy to overlook. slices.BinarySearch isn’t only a membership check; it also tells you where a missing value belongs if you want to preserve the slice’s sort order.

Go 10 Sep 2026 4 min read

Find the First Matching Slice Element in Go with slices.IndexFunc

Searching a slice is easy when the element itself is comparable and you already know the exact value. Real programs often need something slightly different: the first queued job, the first expired token, or the first record whose normalized name matches some input. slices.IndexFunc handles that case directly. You provide a predicate, and it returns the index of the first element for which that predicate is true. If nothing matches, it returns -1.

Go 10 Sep 2026 6 min read

Filter Go Slices in Place with slices.DeleteFunc

Filtering a slice often starts with a small loop: inspect each element, keep the ones you want, and return the shorter result. When changing the original backing array is acceptable, slices.DeleteFunc gives that operation a standard-library name and avoids a hand-written compaction loop. The useful detail is in “changing the original backing array.” slices.DeleteFunc isn’t a general-purpose immutable filter. It removes matching elements in place and returns the shortened slice, so it works best when the caller owns the input and no longer needs its old contents.

Go 10 Sep 2026 5 min read

Filter Go Maps In Place with maps.DeleteFunc

Removing map entries by a condition is common when cleaning caches, pruning stale state, or dropping records that no longer belong in a working set. A for range loop with delete works, but when the operation is simply “delete every entry matching this predicate,” maps.DeleteFunc states that intent directly. The function mutates the map you pass to it. That makes it a good fit for owned, mutable state, but a poor fit when callers still need the original contents.

Go 10 Sep 2026 8 min read

Copy Go Maps with maps.Clone Without Sharing Top-Level State

Copying a Go map is easy to get subtly wrong. Assigning one map variable to another doesn’t duplicate the map, so a write through either variable changes the same underlying map. Since Go 1.21, the standard library’s maps.Clone function gives you a concise way to make a separate top-level map. There is one boundary worth understanding before using it: maps.Clone is a shallow clone. Adding, deleting, or replacing entries in the clone won’t change the original map, but nested maps, slices, pointers, and other reference-bearing values can still refer to the same underlying data.

Go 10 Sep 2026 7 min read

Compare Go Slices with Custom Equality Using slices.EqualFunc

Two slices can represent the same information without being directly comparable element by element. One side might contain structs while the other contains strings. Text may need case-insensitive comparison. IDs may arrive in different concrete types even though your application treats them as the same value. When equality depends on a rule rather than Go’s == operator, slices.EqualFunc puts that rule in one place and handles the slice traversal for you.

Go 10 Sep 2026 6 min read

Compare Go Slices Lexicographically with slices.Compare

Sometimes equality isn’t enough. You may need to order version components, compare path segments, choose which byte sequence comes first, or sort records by a slice-valued key. Writing that comparison by hand is straightforward, but the prefix case and the meaning of the return value are easy places to introduce small bugs. For slices whose element type is ordered, slices.Compare provides the standard lexicographic comparison directly. It compares elements from left to right and, when all shared elements match, treats the shorter slice as smaller.

Go 10 Sep 2026 5 min read

Combine Go Slices with slices.Concat

Combining several slices often starts as a tiny append expression and ends with an ownership question: did the result reuse one of the input backing arrays, and can a later append or mutation affect data another part of the program still uses? Since Go 1.22, slices.Concat gives this operation a direct standard-library form. It combines multiple slices into a new slice, which is especially useful when the result should be treated as its own collection rather than as an extension of one input.

Go 10 Sep 2026 6 min read

Check Slice Predicates in Go with slices.ContainsFunc

Sometimes you don’t need the matching element or its position. You only need to answer a yes-or-no question: does this slice contain anything that satisfies a condition? For that case, slices.ContainsFunc is more direct than writing an index loop or calling slices.IndexFunc and comparing its result with -1. It accepts a predicate, checks elements in order, and returns as soon as one matches. What slices.ContainsFunc does The function accepts any slice element type because the predicate decides what counts as a match:

Go 10 Sep 2026 9 min read

Build Lazy Iterators in Go with iter.Seq

A Go API that returns a slice is pleasantly simple, but a slice isn’t always the right contract. Sometimes the caller only needs the first matching value. Sometimes producing each value requires work. Sometimes the complete result could be large enough that building it up front is wasteful. Go 1.23 gives those APIs a standard alternative: iter.Seq. It represents a sequence that produces values on demand and works directly with a for range loop. The useful part isn’t just new syntax. An iter.Seq can hide a container’s representation, avoid an intermediate result slice, and stop producing values as soon as the caller stops iterating.

Go 10 Sep 2026 7 min read

Build Go Maps from Iterators with maps.Collect

An iterator is a convenient way to produce key-value pairs without deciding up front where they’ll be stored. Eventually, though, an API may need an ordinary map. Writing the collection loop yourself is straightforward, but Go 1.23 gives that boundary a standard name: maps.Collect. maps.Collect consumes an iter.Seq2, stores each yielded pair in a newly allocated map, and returns that map. It’s a small helper, but it makes ownership clear: the sequence produces data; Collect creates the destination.

Go 10 Sep 2026 6 min read

Append Iterator Values to Go Slices with slices.AppendSeq

An iterator is convenient while data is flowing through a pipeline, but sooner or later you may need those values in a slice. If you already have a destination slice, collecting the iterator separately and then appending it creates an unnecessary intermediate step. Go 1.23 added slices.AppendSeq for exactly this boundary. It consumes an iter.Seq, appends each yielded value to an existing slice, and returns the resulting slice. What slices.AppendSeq does The function has a compact signature:

Go 09 Sep 2026 8 min read

Control Structured Log Output in Go with slog.LogValuer

Passing a struct directly to slog is convenient until that struct grows a field that should never appear in logs. An access token, session secret, internal note, or large payload can turn an ordinary diagnostic line into a security problem or an expensive blob of noise. Go’s slog.LogValuer interface gives a type control over its own structured log representation. Instead of teaching every call site which fields are safe, you can define that representation next to the type and let slog use it wherever the value is logged.

Go 08 Sep 2026 9 min read

Use Go Timers Correctly After Go 1.23

Timer code in Go has accumulated a surprising amount of folklore. Older examples warn that time.After leaks resources, insist that every stopped timer channel must be drained, and wrap Timer.Reset in careful stop-and-drain sequences. Those rules were important for older Go programs. They are not all current rules. Go 1.23 changed the implementation and guarantees of channel-based timers. Unreferenced timers can now be garbage collected before they fire, and timer channels use synchronous semantics that prevent stale values after Stop or Reset returns. The result is simpler timer code—but only when the program is actually using the new semantics.

Go 08 Sep 2026 7 min read

Run Cleanup After Context Cancellation with context.AfterFunc

Cancellation often means more than telling a goroutine to stop. A blocked operation may need to be interrupted, a temporary resource may need cleanup, or some state may need to be released as soon as a request deadline expires. A common approach is to start another goroutine that waits on ctx.Done(). That works, but it adds lifecycle code every time you need cancellation-triggered behavior. Since Go 1.21, the standard context package provides context.AfterFunc for this job.

Go 08 Sep 2026 7 min read

Detach Go Work Safely with context.WithoutCancel

Request cancellation is usually exactly what a Go service wants. When a client disconnects or a request deadline expires, database calls, HTTP requests, and other downstream work should normally stop too. Sometimes one small piece of work has a different lifetime. A handler may need to enqueue an audit record, finish a bounded cache update, or send a best-effort notification after the request itself is no longer alive. Passing the request context directly makes that work inherit cancellation. Replacing it with context.Background() avoids cancellation, but also throws away useful request-scoped values.

Go 08 Sep 2026 7 min read

Contain Untrusted File Access in Go with os.Root

Applications often combine a trusted directory with a file name that came from somewhere less trusted: an HTTP request, archive entry, manifest, job message, or database row. The obvious implementation is also a common security boundary mistake: path := filepath.Join("./uploads", userName) f, err := os.Open(path) If userName can select a path outside ./uploads, the application may expose files it never intended to touch. Even careful string validation becomes harder when symbolic links and concurrent filesystem changes enter the picture.

Go 07 Sep 2026 11 min read

Suppress Duplicate Concurrent Work in Go with singleflight

A service can become overloaded even when each individual request is reasonable. Imagine a popular product whose cached record expires. Fifty requests arrive almost together, all observe the same cache miss, and all start the same database query. The problem is not ordinary parallelism. Those requests are doing duplicate work for the same result at the same time. golang.org/x/sync/singleflight provides a small mechanism for suppressing that duplication inside one Go process. For a given key, one caller performs the work while concurrent callers for the same key wait and receive the same result. Calls using different keys can still perform their own work.

Go 07 Sep 2026 8 min read

Stream Data Between Go Components with io.Pipe

Many Go APIs meet at io.Reader and io.Writer. That makes components easy to compose until both sides want to drive the operation. A compressor may want an io.Writer where it can emit bytes incrementally, while an uploader wants an io.Reader from which it can pull those bytes. One tempting solution is to write everything into a bytes.Buffer first and upload it afterward. That works, but it turns a streaming pipeline into a whole-payload allocation.

Go 07 Sep 2026 7 min read

Reject Unknown JSON Fields in Go API Requests

Go makes it pleasantly simple to decode JSON into a struct. That convenience also hides a compatibility decision that matters at API boundaries: by default, fields that do not map to the destination struct are ignored. For internal data this can be useful. For an HTTP request, it can turn a typo into a silent behavior change. A client may send "expires_inn": 3600 while the server expects "expires_in". The JSON is valid, decoding can succeed, and the server may continue with a zero value or a default. The caller receives no direct signal that the field it thought it supplied was never used.