The Modern Toolkit

Updated

July 30, 2026

The Modern 2026 Toolkit

A senior Go engineer is defined by their tools. Using standard grep/find is slow. Upgrade your terminal.

General Tools (Rust-powered, Go-essential)

These aren’t written in Go, but every Go dev uses them. 1. ripgrep (rg): The fastest text search. * rg "func main" -t go: Find main in Go files only. 2. fd: Faster find. * fd -e go: Find all Go files. 3. fzf: Fuzzy finder. Pipe fd into fzf to open files instantly. 4. jq: JSON processor. Crucial for debugging API responses or logs (zap/slog JSON output).

Go-Specific Tools

gopsutil

If you are building system tools (agents, monitors), github.com/shirou/gopsutil is the standard for reading CPU/Memory/Disk stats cross-platform.

go fix Modernizers (New in 1.26)

Go 1.26 extends go fix modernizers and adds inline directives for local fixes.

go fix -modernize ./...

Examples of what it fixes: * Replaces manual loops with slices.Contains. * Updates older interface{} to any. * Updates deprecated package usage.

Inline fix for one location:

//go:fix inline
func has(xs []string, x string) bool {
    for _, v := range xs {
        if v == x {
            return true
        }
    }
    return false
}

govulncheck

The official vulnerability scanner.

go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

It tells you if your code actually calls the vulnerable function in a dependency. This drastically reduces false positives compared to generic scanners (Dependabot).

Workflow Integration

Don’t run these manually. Put them in a Makefile or Taskfile (Task is a modern Make alternative written in Go).

# Taskfile.yaml
tasks:
  audit:
    cmds:
      - go vet ./...
      - staticcheck ./...
      - govulncheck ./...

Worked example

slices / maps modern stdlib helpers vs hand-rolled loops.

Save as util.go and util_test.go. Then:

go mod init example
go test -v
// util.go
package main

import (
    "maps"
    "slices"
)

func has(xs []string, x string) bool {
    return slices.Contains(xs, x)
}

func cloneMap(m map[string]int) map[string]int {
    return maps.Clone(m)
}
// util_test.go
package main

import "testing"

func TestHas(t *testing.T) {
    xs := []string{"a", "b", "c"}
    if !has(xs, "b") || has(xs, "z") {
        t.Fatal("contains mismatch")
    }
}

func TestCloneMap(t *testing.T) {
    m := map[string]int{"x": 1}
    c := cloneMap(m)
    c["x"] = 9
    if m["x"] != 1 {
        t.Fatal("clone should be independent")
    }
}

Expected output:

=== RUN   TestHas
--- PASS: TestHas (0.00s)
=== RUN   TestCloneMap
--- PASS: TestCloneMap (0.00s)
PASS

More examples

Table of “grep-friendly” symbols your toolkit will find.

package main

import "fmt"

// AuditTarget is intentionally distinctive for rg demos.
func AuditTarget() string { return "ok" }

func main() {
    fmt.Println(AuditTarget())
}
# in a shell with ripgrep installed:
# rg 'func AuditTarget' -t go
go run .

Runnable example

Note: Tools like rg, staticcheck, and govulncheck are external CLIs. This stdlib demo captures the modernizer idea: replace a hand-rolled loop with slices.Contains, and run go vet-friendly code under go test.

Save as modern.go and modern_test.go. Then:

go mod init example
go test -v
go vet ./...
// modern.go
package main

import "slices"

// legacyHas is the pre-slices style many codebases still have.
func legacyHas(xs []string, x string) bool {
    for _, v := range xs {
        if v == x {
            return true
        }
    }
    return false
}

// modernHas is the 1.21+ equivalent (what go fix -modernize targets).
func modernHas(xs []string, x string) bool {
    return slices.Contains(xs, x)
}
// modern_test.go
package main

import "testing"

func TestHas(t *testing.T) {
    xs := []string{"go", "rust", "zig"}
    if !legacyHas(xs, "go") || !modernHas(xs, "go") {
        t.Fatal("expected to find go")
    }
    if legacyHas(xs, "c") || modernHas(xs, "c") {
        t.Fatal("did not expect c")
    }
    if legacyHas(xs, "rust") != modernHas(xs, "rust") {
        t.Fatal("implementations diverged")
    }
}

Expected output:

=== RUN   TestHas
--- PASS: TestHas (0.00s)
PASS

What to notice: Stdlib slices / maps replace a lot of utility code. Keep a small go test + go vet loop before pulling heavier linters. govulncheck still needs a separate install—run it in CI on real modules.

Try next: Run go fix -modernize ./... on a module that still uses interface{} and manual contains loops. Pipe JSON logs through jq in your shell.