Skip to content

Archive

Golang

70 articles
Go 13 Sep 2026 4 min read

Transform Unicode Text with strings.Map in Go

strings.Map applies one function to every rune in a UTF-8 string and builds a string from the returned runes. A mapping function can preserve a rune, replace it, or remove it entirely. That makes the API a compact fit for transformations whose rule is naturally expressed one Unicode code point at a time. mapped := strings.Map(func(r rune) rune { if r == '_' { return '-' } return r }, input) The operation is rune-oriented rather than byte-oriented. ASCII input still follows the same contract, but multibyte UTF-8 sequences arrive at the callback as decoded rune values.

Go 13 Sep 2026 4 min read

Split Text with Custom Rune Boundaries Using strings.FieldsFunc in Go

strings.FieldsFunc treats selected Unicode code points as boundaries and returns the non-empty text between them. That behavior fits inputs where separators belong to a class rather than one fixed substring: commas and semicolons, several punctuation marks, or any rune accepted by a deterministic predicate. fields := strings.FieldsFunc(input, func(r rune) bool { return r == ',' || r == ';' }) For alpha,,beta;gamma;, the result is []string{"alpha", "beta", "gamma"}. Consecutive matching runes form a boundary region, and matching runes at either edge do not produce empty elements.

Go 13 Sep 2026 4 min read

Split Once with strings.Cut in Go

strings.Cut separates a string around the first occurrence of a delimiter and reports whether that delimiter was present. That three-result contract matters in parsers where a missing separator is different from a separator followed by an empty value. before, after, found := strings.Cut(input, "=") When the separator exists, before contains the text preceding its first occurrence and after contains the remainder. When it does not exist, the function returns the original string, an empty second string, and false.

Go 13 Sep 2026 5 min read

Set Per-Request Read Deadlines with http.ResponseController in Go

A server-level read timeout applies one policy across connections, but a particular handler can have a narrower request-body budget. Go’s http.ResponseController exposes SetReadDeadline for that case. The deadline covers reading the request, including its body, and gives handler code a direct boundary for input that arrives too slowly. This control is different from limiting body size. A byte limit constrains how much data a handler accepts; a read deadline constrains how long reads may continue. Endpoints that accept streamed or uploaded data often need both dimensions considered separately.

Go 13 Sep 2026 5 min read

Replace Non-Overlapping Substrings with strings.ReplaceAll in Go

strings.ReplaceAll replaces every non-overlapping occurrence of one literal string with another. There is no regular-expression syntax, callback, or token model involved: matching is based on the exact byte sequence supplied as old. result := strings.ReplaceAll("api/v1/users", "/v1/", "/v2/") The result is api/v2/users. This small contract makes the function suitable for fixed substitutions where every match receives the same replacement.

Go 13 Sep 2026 3 min read

Remove Prefixes with strings.CutPrefix in Go

Prefix removal often carries two pieces of information: the remaining text and whether the expected prefix was present. strings.CutPrefix represents both results in one operation instead of separating a prefix test from the removal that follows it. That distinction matters when an unchanged string is a valid result. strings.TrimPrefix returns the input unchanged when the prefix is absent, so its return value alone cannot report presence. strings.CutPrefix returns the remainder plus a boolean that preserves that fact explicitly.

Go 13 Sep 2026 4 min read

Remove Explicit Suffixes with strings.CutSuffix in Go

strings.CutSuffix removes one exact trailing string and reports whether that suffix was present. The boolean result is the key distinction from operations that only return transformed text: callers can keep suffix recognition separate from the remaining content. base, found := strings.CutSuffix(name, ".json") If name ends in .json, base contains the preceding text and found is true. Otherwise, base is the original string and found is false. The operation does not scan for a matching fragment in the middle and does not repeatedly strip the suffix.

Go 13 Sep 2026 4 min read

Bound HTTP Request Bodies with http.MaxBytesReader in Go

An HTTP handler that decodes a request body without a byte limit can consume far more input than its application-level schema suggests. A JSON object with three fields may still arrive inside a multi-gigabyte body. Decoder validation controls structure; it does not establish a transport-sized boundary. Go’s http.MaxBytesReader places that boundary directly around the request body. It returns an io.ReadCloser that permits reads up to a configured limit and reports an error when code attempts to read beyond it.

Go 12 Sep 2026 4 min read

Track Goroutine Lifetimes with sync.WaitGroup.Go in Go

sync.WaitGroup.Go combines goroutine creation with task accounting. Added in Go 1.25, the method removes a small but consequential gap between incrementing a wait-group counter and starting the goroutine that will eventually decrement it. The method does not change what a WaitGroup represents. It still tracks a set of tasks and lets another goroutine block until that set is complete. The difference is that registration and goroutine launch now share one operation.

Go 12 Sep 2026 5 min read

Run Cancellation Callbacks with context.AfterFunc in Go

context.AfterFunc attaches a callback to context cancellation without adding a goroutine that waits only on ctx.Done(). When the context becomes done, the callback starts in its own goroutine. The small API hides a concurrency boundary that matters when the callback mutates shared state, interrupts blocking I/O, or competes with normal completion. The function arrived in Go 1.21 and returns a stop function. That return value is not a general cancellation handle for the callback. It controls the association between the context and the callback, with precise behavior once cancellation and callback startup begin to race.

Go 12 Sep 2026 5 min read

Preserve Cancellation Causes in Go Contexts

A canceled Go context normally reports one of two broad states through ctx.Err(): context.Canceled or context.DeadlineExceeded. That is enough to stop work, but it can discard the event that triggered cancellation. A worker failure, shutdown request, quota rejection, and explicit abort can all collapse into the same context.Canceled value. Go provides cause-aware context functions for cases where the cancellation signal and the diagnostic error need to travel together. context.WithCancelCause creates a derived context whose cancel function accepts an error, while context.Cause retrieves the recorded cause.

Go 12 Sep 2026 5 min read

Interleave HTTP Request Reads and Response Writes in Go

An HTTP handler that writes its response before finishing the request body has a protocol-sensitive edge case. With HTTP/1, Go’s server normally consumes the unread request body before it begins writing the response. That default keeps ordinary handlers simple, but it conflicts with handlers that intentionally exchange data in both directions at the same time. http.ResponseController.EnableFullDuplex changes that behavior for the current request. It tells the server that the handler intends to interleave reads from Request.Body with writes to the ResponseWriter.

Go 12 Sep 2026 5 min read

Flush Buffered HTTP Data with http.ResponseController in Go

An HTTP handler can write bytes without making those bytes immediately visible to the client. The server, transport, middleware, or another layer may buffer response data. For handlers that emit incremental output, http.ResponseController.Flush provides an explicit request to push buffered data toward the client. The operation belongs to the current response. It does not turn a normal handler into a separate transport protocol, and it does not guarantee that every intermediary on the network will forward each chunk at the same instant. Its useful contract is narrower: ask the active response writer to flush data it has buffered.

Go 12 Sep 2026 4 min read

Detach Go Context Cancellation with context.WithoutCancel

A Go context usually ties a unit of work to the lifetime of its parent. Cancel an HTTP request context, and derived contexts observe that cancellation. This propagation is the normal contract, but some follow-up operations need a different lifetime while still carrying request-scoped values. Go 1.21 added context.WithoutCancel for that boundary. It returns a context that can resolve values through its parent but does not inherit the parent’s cancellation state or deadline.

Go 12 Sep 2026 5 min read

Cache Concurrent Initialization Results with sync.OnceValue in Go

sync.OnceValue turns a function into a concurrency-safe, one-time computation whose result is returned on every call. The first caller performs the computation. Concurrent callers wait for that call to finish, and later callers receive the stored result without running the function again. This differs from using sync.Once with a separate result variable. The value and its one-time initialization are packaged behind a function, which makes the lifetime of the cached result explicit in the place where that function is stored.

Go 10 Sep 2026 7 min read

Set Per-Response Write Deadlines in Go with http.ResponseController

A server-wide WriteTimeout is a useful safety net, but some handlers have different timing needs. A small JSON response and a streaming export shouldn’t necessarily share the same write budget. When the deadline belongs to one response rather than the whole server, Go’s http.ResponseController gives the handler a direct way to set it. http.ResponseController.SetWriteDeadline applies a write deadline to the current response. It also solves a practical middleware problem: instead of asserting a concrete optional interface at every call site, a handler can ask the controller to find the capability through compatible ResponseWriter wrappers.

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 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 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.

Go 07 Sep 2026 8 min read

Handle Buffered Write Errors Correctly in Go

Buffering output can reduce write overhead, but it also changes when an I/O failure becomes visible. With an unbuffered writer, a call to Write normally reaches the underlying destination immediately. With bufio.Writer, a successful call may only mean that the bytes were accepted into memory. The actual write to a file, socket, pipe, or other destination can happen later, often during Flush. That distinction creates a common production bug: code checks every apparent write, defers Flush, and still returns success after the final flush fails.

Go 04 Sep 2026 9 min read

Understand Escape Analysis and Heap Allocations in Go

A Go program can create many values without you choosing whether each value lives on a goroutine stack or in heap memory. The compiler usually makes that decision for you. This becomes important when a hot path allocates more than expected. A small helper function may look harmless, yet a value it creates can outlive the function call and require heap storage. More heap allocation can mean more work for the garbage collector, but changing code blindly to avoid the heap can make a program harder to understand without producing a measurable benefit.

Go 04 Sep 2026 10 min read

Coordinate Shared State with sync.Cond in Go

A goroutine sometimes cannot make progress until shared state changes. A worker may need to wait until a queue contains an item. A producer may need to wait until that queue has free capacity. Several goroutines may need to sleep until a service becomes ready. Polling the state in a loop wastes CPU or forces you to invent arbitrary sleep intervals. Channels solve many coordination problems more directly, but they are not always a natural fit when several goroutines already share state protected by a mutex and need to wait for predicates over that state.

Go 03 Sep 2026 11 min read

Use sync.Pool for Temporary Object Reuse in Go

Repeatedly allocating short-lived helper objects can become expensive in a hot path. A formatter may create temporary buffers for every request, an encoder may allocate scratch space for every record, or a parser may repeatedly construct helper objects that are discarded immediately after use. Go’s sync.Pool can reuse some of those temporary objects across independent operations. That can reduce allocation work and garbage-collector pressure when the same kind of object is created frequently under load.