Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
320 posts found
HTTP Clients in Go: http.Client, Timeouts, Cancellation with context, Reusing the Transport and Retries
Backend PART 19

HTTP Clients in Go: http.Client, Timeouts, Cancellation with context, Reusing the Transport and Retries

In Go, http.DefaultClient has no timeout; in production you use one shared http.Client, Transport timeouts for each phase, Client.Timeout per attempt and a context for the total budget. Which timeout covers which phase, Go 1.27 reading small bodies on Close to reuse the connection, MaxIdleConnsPerHost, checking 4xx/5xx, retries with backoff, jitter and Retry-After, idempotency, and testing a client with httptest.

15 Nov 2026 12 min 11
io.Reader/io.Writer, os and bufio in Go: File Operations, Composing Streams and embed
Backend PART 18

io.Reader/io.Writer, os and bufio in Go: File Operations, Composing Streams and embed

In Go a file, a gzip stream, an HTTP body and a string all satisfy the same single-method io.Reader; when a function takes an io.Reader instead of a file name, a 1 GB log is processed with constant memory. bufio.Scanner's 64 KB line limit and silent stop, the Close error of a written file, flushing csv.Writer, composition with LimitReader/MultiWriter/TeeReader, and embedding an e-mail template into the binary with //go:embed.

15 Nov 2026 12 min 9
The slices, maps, sort and cmp Packages in Go: Sorting, Searching, Grouping and Collection Work with Iterators
Backend PART 17

The slices, maps, sort and cmp Packages in Go: Sorting, Searching, Grouping and Collection Work with Iterators

In Go, multi-field sorting combines slices.SortStableFunc with cmp.Or and cmp.Compare; map iteration order changes on every run, and sorted keys need slices.Sorted(maps.Keys(m)). Adding ?sort= and a category summary to Bookstore, LINQ counterparts, backing-array traps with append and slices.Delete, json/v2 map order, measuring sort against slices, and Turkish sorting with x/text/collate.

15 Nov 2026 12 min 11
The time Package in Go: time.Time, Duration, Formatting with the Reference Time ("2006-01-02"), Time Zones and the Monotonic Clock
Backend PART 16

The time Package in Go: time.Time, Duration, Formatting with the Reference Time ("2006-01-02"), Time Zones and the Monotonic Clock

In Go a date format is not given with codes such as yyyy-MM-dd but by showing how the reference time 2006-01-02 15:04:05 is written; "yyyy-MM-dd" does not fail, it is printed as it is. Duration, json/v2 giving Duration no default format, time zones and the three-hour shift from post 11, time/tzdata on scratch images and Windows, a delivery estimate on the warehouse clock, the monotonic clock and Equal, and the time.After trap.

15 Nov 2026 12 min 9
Working with Strings in Go: strings, strconv, fmt Verbs, Bytes vs Runes and Turkish Characters
Backend PART 15

Working with Strings in Go: strings, strconv, fmt Verbs, Bytes vs Runes and Turkish Characters

In Go a string is an immutable sequence of UTF-8 bytes, and the strings package ignores language: strings.EqualFold does not treat "istanbul" and "İSTANBUL" as equal, and Turkish rules need unicode.TurkishCase. Normalizing and validating ISBNs, strconv error types, reading Turkish-format prices, fmt verbs and go vet, measuring strings.Builder, and RE2-based regexp.

15 Nov 2026 14 min 9
From Go 1.22 to 1.27: Loop Variables, Routing, range-over-func, Green Tea GC, json/v2 and Generic Methods
Backend PART 14

From Go 1.22 to 1.27: Loop Variables, Routing, range-over-func, Green Tea GC, json/v2 and Generic Methods

In Go, the go line in go.mod and GODEBUG settings decide a release's behaviour, but removed settings end that protection: because Go 1.27 removed asynctimerchan, the timer behaviour of a module saying go 1.22 changed with nothing but a toolchain upgrade. The changes from 1.22 to 1.27 that matter for backend work, the nil check fix, os.Root, uuid, measuring the new allocator, what moving to json/v2 does to clients, and go fix modernizers.

15 Nov 2026 15 min 7
Taking a Go Service to Production: slog, Configuration, Graceful Shutdown, pprof and Small Containers
Backend PART 13

Taking a Go Service to Production: slog, Configuration, Graceful Shutdown, pprof and Small Containers

Getting a Go service ready for production means reading settings from environment variables into a struct, writing JSON logs with log/slog, catching SIGTERM with signal.NotifyContext and exiting through server.Shutdown, adding health checks and serving pprof on a separate port. In Bookstore: slog with the request ID, a drain delay, measuring container-aware GOMAXPROCS and GOMEMLIMIT, builds with -trimpath and ldflags, and a 4.72 MB distroless image.

15 Nov 2026 16 min 9
Testing in Go: the testing Package, Table-Driven Tests, httptest, Benchmarks and synctest
Backend PART 12

Testing in Go: the testing Package, Table-Driven Tests, httptest, Benchmarks and synctest

Testing in Go needs no framework: _test.go files, table-driven tests with t.Run, hand-written fakes that satisfy an interface, and httptest are enough. In Bookstore: a table test for the stock rule, a fixed clock, handler tests through the mux, synctest with Go 1.27's httptest.NewTestServer, a fuzz test that finds a negative amount bug, a benchmark of generic code, an integration test against SQL Server, coverage and go test -race.

15 Nov 2026 17 min 7
From Go to SQL Server and PostgreSQL: database/sql, go-mssqldb, Connection Pools, Transactions and sqlc
Backend PART 11

From Go to SQL Server and PostgreSQL: database/sql, go-mssqldb, Connection Pools, Transactions and sqlc

Go talks to databases through database/sql: sql.Open returns a connection pool rather than a connection, the driver registers through a blank import, and the order plus the stock update go into one transaction with BeginTx, defer Rollback and Commit. Bookstore's orders in SQL Server with go-mssqldb: pool settings, preventing lost updates with a conditional UPDATE, Scanner/Valuer from decimal to kuruş, the rows.Close leak, the datetime2 time zone trap, pgx, and where sqlc stands on SQL Server.

15 Nov 2026 21 min 7
JSON and Request Validation in Go: encoding/json, json/v2, Struct Tags and Body Limits
Backend PART 10

JSON and Request Validation in Go: encoding/json, json/v2, Struct Tags and Body Limits

Reading a JSON body safely in Go takes a Content-Type check, a size limit with MaxBytesReader, DisallowUnknownFields and a single-value check, while encoding/json v1 matches field names regardless of case and takes the last of a repeated field. POST /api/orders in Bookstore, missing values with *int, a validation list from an errors.Join tree, Problem Details with the same contract as ASP.NET Core, Go 1.27's json/v2 differences, and carrying prices in kuruş instead of float64.

15 Nov 2026 14 min 6
HTTP Servers with net/http: ServeMux Pattern Routing, Handlers, Middleware and Timeouts
Backend PART 09

HTTP Servers with net/http: ServeMux Pattern Routing, Handlers, Middleware and Timeouts

For an HTTP service in Go the standard library is enough: since 1.22 ServeMux matches method and wildcard patterns with a most-specific-wins rule, and middleware is an ordinary function that wraps a handler. Moving the Bookstore API into the httpapi package, RequestID and Logging middleware, CORS and CrossOriginProtection, the 307 redirect, the pattern conflict panic, WriteTimeout not stopping the handler, and http.Server timeouts against slowloris.

15 Nov 2026 13 min 7
Concurrency Patterns in Go: context, sync, errgroup, Worker Pools and Goroutine Leaks
Backend PART 08

Concurrency Patterns in Go: context, sync, errgroup, Worker Pools and Goroutine Leaks

In Go, data accessed concurrently is either guarded by a mutex or handed to its owner over a channel; an unguarded map crashes the process, while an unguarded counter silently produces duplicate order IDs. Concurrent map writes and the race detector in Bookstore, fixing Service and memstore with mutexes, cancellation and deadlines with context, WaitGroup.Go, a 10,000-invoice worker pool with errgroup, Go 1.27's goroutineleak profile, and running a 15-minute test instantly with synctest.

15 Nov 2026 14 min 8
Blog Map