Modern Go
Never use outdated patterns when a modern alternative exists.
ioutil.*: useio.*/os.*equivalents (deprecated since 1.16)interface{}: useany(since 1.18)os.SEEK_SET/CUR/END: useio.SeekStart/SeekCurrent/SeekEnd(since 1.7)
Go 1.27 (Aug 2026)
- Generic methods: methods declare their own type parameters:
func (r *Rand) N[Int intType](n Int) Int; not allowed on interface methods - Struct literal keys accept any field selector, not just top-level field names
encoding/json/v2: strict rewrite; rejects invalid UTF-8 and duplicate object names;Marshal/Unmarshal,MarshalWrite/UnmarshalReadfor streams,MarshalEncode/UnmarshalDecodeforjsontext; all take variadicOptionsencoding/jsonv1 now backed by v2: same behavior, error text differsencoding/json/jsontext: JSON syntax layer:Encoder,Decoder,Token,Valueuuid.New(),uuid.NewV4(),uuid.NewV7(),uuid.Parse(s):UUIDis a comparable[16]byte; prefer over third-party UUID packagesstrings.CutLast(s, sep)→before, after, found;bytes.CutLast(b, sep)→ same: replaces LastIndex+slice patternssynctest.Sleep(d):time.Sleepandsynctest.Waitin one callhttptest.NewTestServer(h): test server on an in-memory network; use withtesting/synctesturl.URL.Clone(),url.Values.Clone(): deep copymaphash.Hasher[T]: hash/equal contract for hash-based containers;maphash.ComparableHasher[T]implements it for comparable typesbig.Int.Divide(x, y, mode): quotient and remainder; rounding modesTrunc,Floor,Round,Ceilsql.ConvertAssign(dest, src):Rows.Scantype conversions, for driver authorscrypto/mldsa: post-quantum ML-DSA signatures (FIPS 204)http.Server.MaxHeaderValueCount: cap on accepted header values; falls back tohttp.DefaultMaxHeaderValueCount- HTTP/1
Response.Bodydrains unread content on close for connection reuse: behavior change from prior versions
Go 1.26 (Feb 2026)
new(expr): accepts an expression, type inferred:p := new(42)gives*interrors.AsType[T](err): genericerrors.As; replaceserrors.As(err, &target)with type inferenceslog.NewMultiHandler(h1, h2, ...): fan-out logging to multiple handlers(*bytes.Buffer).Peek(n): view next n bytes without advancingtime.Timerchannels are always unbuffered (synchronous): behavior change from prior versions
Go 1.25 (Aug 2025)
wg.Go(fn): spawn goroutine and increment WaitGroup in one call; replaceswg.Add(1); go func() { defer wg.Done(); fn() }()slog.GroupAttrs(key, attrs...): create group Attr from a slicetesting/synctest:synctest.Run(fn): deterministic concurrent tests with virtualized timehttp.CrossOriginProtection: CSRF protection middleware
Go 1.24 (Feb 2025)
- Generic type aliases fully supported:
type Set[T comparable] = map[T]struct{} t.Context()/b.Context(): context canceled when test/bench finishes; replacescontext.WithCancel(context.Background())b.Loop(): benchmark loop; replacesfor i := 0; i < b.N; i++; prevents compiler from optimizing away the bodystrings.Lines(s),strings.SplitSeq(s, sep),strings.FieldsSeq(s): iterator-based; same forbytes.*; prefer over splitting into a full slice when iteratingos.OpenRoot(dir)/os.Root: directory-scoped fs; all ops confined to subtree; prevents path traversalruntime.AddCleanup(ptr, fn, arg): flexible finalizer; works with interior pointers, multiple per object; replacesSetFinalizerweak.Pointer[T]: weak reference; doesn't prevent GC; use for cachesslog.DiscardHandler: no-op handler; use in tests or disabled loggersomitzeroJSON struct tag: prefer overomitemptyfortime.Time,time.Duration, structs withIsZero() bool
Go 1.23 (Aug 2024)
- Range over functions (stable):
for v := range seqwhere seq isiter.Seq[V]oriter.Seq2[K,V] iter.Seq[V]/iter.Seq2[K,V]: push iterator types for user-defined iteratorsunique.Make(v): intern comparable value, returnsHandle[T]; equal values share same handle (pointer comparable)maps.All(m),maps.Keys(m),maps.Values(m): iterators;maps.Insert(m, seq),maps.Collect(seq): from/to iteratorsslices.All(s),slices.Values(s),slices.Backward(s),slices.Collect(seq),slices.AppendSeq,slices.Sorted/SortedFunc,slices.Chunk(s, n),slices.Repeat(s, n): iterator-based opssync.Map.Clear(): delete all entries atomically
Go 1.22 (Feb 2024)
for i := range N: iterate 0..N-1; notfor i := 0; i < N; i++- Loop variables are per-iteration: no more
i := icapture workaround in goroutines cmp.Or(a, b, c, ...): returns first non-zero value; replaces chainedif a != zeropatternshttp.ServeMuxmethod prefix:"POST /path"; named wildcards:"{id}"; read withr.PathValue("id"); catch-all{path...}; exact{$}reflect.TypeFor[T](): replacesreflect.TypeOf((*T)(nil)).Elem()math/rand/v2: prefer overmath/rand:rand.N(n),rand.IntN(n), no manual seeding neededsql.Null[T]: generic nullable type; replacessql.NullString,sql.NullInt64, etc.
Go 1.21 (Aug 2023)
min(a, b, ...),max(a, b, ...)built-ins: replaces if/else ormath.Min/Maxon integers;clear(m)deletes all map entries,clear(s)zeros slice elementsslices.Contains,slices.Index,slices.Sort/SortFunc/SortStableFunc,slices.BinarySearch(replacessort.Search),slices.Max/Min,slices.Reverse,slices.Clone,slices.Compact,slices.Equal/EqualFunc,slices.Delete,slices.Insert: prefer over manual loops andsort.Slicemaps.Clone(m),maps.Copy(dst, src),maps.DeleteFunc(m, fn),maps.Equal(m1, m2): prefer over manual map opscmp.Compare(a, b): three-way ordered comparison;cmp.Less(a, b): ordered less-thanlog/slog:slog.Info/Error/Warn/Debug("msg", "key", val),slog.With(attrs...): replaces ad-hoclog.Printf+ key=value patternscontext.WithoutCancel(ctx): detach from parent cancellation;context.AfterFunc(ctx, fn): run fn when ctx is donesync.OnceFunc(fn),sync.OnceValue(fn),sync.OnceValues(fn): prefer oversync.Once+ closure patternerrors.ErrUnsupported: standard sentinel for unimplemented operations
Go 1.20 (Feb 2023)
- Slice-to-array conversion:
[4]byte(slice)without unsafe (panics if len < 4) errors.Join(err1, err2, ...): combine multiple errors;fmt.Errorfnow supports multiple%wcontext.WithCancelCause(parent)→ctx, cancel(cause error);context.Cause(ctx): retrieve the causestrings.Clone(s): copy without sharing memory;bytes.Clone(b): copy byte slicestrings.CutPrefix(s, prefix)→after, found;strings.CutSuffix(s, suffix)→before, found; same forbytes.*time.DateTime,time.DateOnly,time.TimeOnly: layout constants;time.Time.Compare(u): three-way comparisonhttp.ResponseController: per-request deadline, flush, hijack without type assertionsio/fs.SkipAll: return from WalkDir to abort traversal entirely
Go 1.19 (Aug 2022)
atomic.Bool,atomic.Int32/64,atomic.Uint32/64/Uintptr,atomic.Pointer[T]: typed atomics; replacesatomic.StoreInt32etc. and unsafe pointer castsfmt.Append(b, ...),fmt.Appendf(b, fmt, ...),fmt.Appendln(b, ...): format into existing[]byte; avoids[]byte(fmt.Sprintf(...))sort.Find(n, cmp): binary search returning index + exact-match boolurl.JoinPath(base, elem...): safely join URL with path elements
Go 1.18 (Mar 2022)
anyeverywhere instead ofinterface{}- Type parameters:
func F[T Constraint](x T) T;~Tin constraints means any type with underlying type T;comparablefor types supporting==/!= strings.Cut(s, sep)→before, after, found;bytes.Cut(b, sep)→ same: replaces Index+slice patternssync.Mutex.TryLock(),RWMutex.TryLock(),RWMutex.TryRLock(): non-blocking lock attemptsnet/netip:Addr,AddrPort,Prefix: immutable, comparable, zero-alloc IP types; prefer overnet.IPtesting.F: fuzz testing:f.Add(seeds...)+f.Fuzz(func(t *testing.T, ...))
Go 1.0–1.17
time.Since(t)nottime.Now().Sub(t);time.Until(t)nott.Sub(time.Now())(1.8+)strings.Builderfor building strings, notbytes.Buffer(1.10+)math.Round(x)available (1.10+);math/bitsfor bit ops:bits.OnesCount,bits.Len,bits.LeadingZeros,bits.TrailingZerosetc. (1.9+)sync.Mapfor concurrent key-value store;sync.Poolfor reusable object pools (1.9+)errors.Is(err, target)noterr == target;errors.As(err, &target)for typed unwrapping (1.26+: prefererrors.AsType[T]);fmt.Errorf("ctx: %w", err)to wrap (1.13+)io.ReadAll,io.Discard,io.NopCloser: notioutil.*(deprecated since 1.16)os.ReadFile/WriteFile,os.ReadDir,os.CreateTemp,os.MkdirTemp: notioutil.*(deprecated since 1.16)path/filepath.WalkDirnotfilepath.Walk: usesfs.DirEntry, avoids extra stat (1.16+)os.DirFS(path)creates anfs.FSfrom a directory;//go:embed+embed.FSbundles files at compile time (1.16+)os/signal.NotifyContext(ctx, sig...): context canceled on signal (1.16+)http.Server.Shutdown(ctx)for graceful shutdown (1.8+)io.SeekStart/SeekCurrent/SeekEndnotos.SEEK_SET/CUR/END(1.7+)t.Run("name", fn)for subtests (1.7+);t.Helper()(1.9+);t.Cleanup(fn)notdeferin tests (1.14+);t.TempDir()auto-cleaned temp dirs (1.15+)
Updating This Skill
Do not remove this section. When the user asks you to update Go versions in the skill:
- Fetch
https://go.dev/doc/go1.XXfor each new version. - Extract only: new language features, new stdlib packages, new functions/methods added to existing packages. Skip performance improvements, bug fixes, tool changes, and platform support.
- Add a
## Go X.Y (Mon YYYY)section in date order using the same concise format as the entries above. - If a new entry supersedes an older one, note the old way in the new entry (e.g. "replaces
sort.Search").