<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dishon Oketch</title>
    <description>The latest articles on DEV Community by Dishon Oketch (@oketch).</description>
    <link>https://dev.to/oketch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3879643%2Fd07e2208-cddd-41f0-8252-4a9c59fcbc20.jpg</url>
      <title>DEV Community: Dishon Oketch</title>
      <link>https://dev.to/oketch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oketch"/>
    <language>en</language>
    <item>
      <title>Essential DevTools Every Go Developer Should Know</title>
      <dc:creator>Dishon Oketch</dc:creator>
      <pubDate>Thu, 23 Apr 2026 02:16:44 +0000</pubDate>
      <link>https://dev.to/oketch/essential-devtools-every-go-developer-should-know-4blj</link>
      <guid>https://dev.to/oketch/essential-devtools-every-go-developer-should-know-4blj</guid>
      <description>&lt;h1&gt;
  
  
  Essential DevTools Every Go Developer Should Know
&lt;/h1&gt;

&lt;p&gt;Go ships with a powerful standard toolchain that many developers underestimate. Beyond writing code, knowing your tools is what separates a developer who fights their environment from one who moves efficiently through it. This article walks through the essential Go dev tools — what they do, when to use them, and why they matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. &lt;code&gt;go run&lt;/code&gt; — Fast Feedback Loop
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;go run&lt;/code&gt; compiles and executes a Go program in a single step without producing a binary artifact. Internally, it compiles to a temporary directory and runs the resulting binary. It's not for production — it's your rapid iteration tool during development.&lt;/p&gt;

&lt;p&gt;For multi-file packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. &lt;code&gt;go build&lt;/code&gt; — Producing Binaries
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; bin/myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go compiles to a statically linked binary by default — no runtime, no VM, no dependencies on the host system. This makes deployment straightforward: copy the binary and run it.&lt;/p&gt;

&lt;p&gt;You can cross-compile for different OS/architectures using environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 go build &lt;span class="nt"&gt;-o&lt;/span&gt; bin/myapp-linux &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly powerful for building Linux binaries from a Mac or Windows machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;code&gt;go fmt&lt;/code&gt; — Enforced Code Style
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;fmt&lt;/span&gt; ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go enforces a single, non-negotiable code style via &lt;code&gt;go fmt&lt;/code&gt;. There are no style debates in Go teams — the formatter decides. It uses tabs for indentation and has strict rules on spacing, braces, and imports.&lt;/p&gt;

&lt;p&gt;Most editors run this on save via &lt;code&gt;gopls&lt;/code&gt;. You should also enforce it in CI to reject unformatted code.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;code&gt;go vet&lt;/code&gt; — Static Analysis
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go vet ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;go vet&lt;/code&gt; performs static analysis to catch bugs the compiler won't flag — mismatched &lt;code&gt;Printf&lt;/code&gt; format verbs, incorrect struct tags, unreachable code, suspicious composite literals, and more.&lt;/p&gt;

&lt;p&gt;It's lightweight and fast. Run it before every commit. In CI, a failing &lt;code&gt;go vet&lt;/code&gt; should block a merge.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;code&gt;go test&lt;/code&gt; — Built-in Testing Framework
&lt;/h2&gt;

&lt;p&gt;Go has testing built into the standard library — no third-party framework needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; ./...                        &lt;span class="c"&gt;# Run all tests&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; TestFunctionName ./... &lt;span class="c"&gt;# Run a specific test with verbose output&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-race&lt;/span&gt; ./...                  &lt;span class="c"&gt;# Run with race condition detector&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-cover&lt;/span&gt; ./...                 &lt;span class="c"&gt;# Show test coverage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test files follow the &lt;code&gt;_test.go&lt;/code&gt; naming convention. The race detector (&lt;code&gt;-race&lt;/code&gt;) is particularly valuable — it instruments memory accesses at runtime to detect concurrent data races, which are otherwise very hard to catch.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. &lt;code&gt;gopls&lt;/code&gt; — The Go Language Server
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gopls&lt;/code&gt; is the official Go language server implementing the Language Server Protocol (LSP). It powers editor features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent autocompletion&lt;/li&gt;
&lt;li&gt;Go-to-definition and find-references&lt;/li&gt;
&lt;li&gt;Inline diagnostics and error highlighting&lt;/li&gt;
&lt;li&gt;Automatic imports management&lt;/li&gt;
&lt;li&gt;Refactoring (rename, extract function)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It integrates with VS Code (via the Go extension), Neovim (via &lt;code&gt;nvim-lspconfig&lt;/code&gt;), GoLand, and most modern editors. For VS Code, installing the official Go extension is all you need — &lt;code&gt;gopls&lt;/code&gt; is bundled and managed automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Delve (&lt;code&gt;dlv&lt;/code&gt;) — The Go Debugger
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/go-delve/delve/cmd/dlv@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delve is the standard debugger for Go. It understands Go's runtime, goroutines, and data structures — unlike GDB, which doesn't handle Go well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dlv debug main.go        &lt;span class="c"&gt;# Start debugging&lt;/span&gt;
dlv &lt;span class="nb"&gt;test&lt;/span&gt; ./pkg/...       &lt;span class="c"&gt;# Debug tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common commands inside the Delve REPL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;break &lt;/span&gt;main.main       &lt;span class="c"&gt;# Set breakpoint&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt;              &lt;span class="c"&gt;# Run until breakpoint&lt;/span&gt;
next                  &lt;span class="c"&gt;# Step over&lt;/span&gt;
step                  &lt;span class="c"&gt;# Step into&lt;/span&gt;
print variableName    &lt;span class="c"&gt;# Inspect a variable&lt;/span&gt;
goroutines            &lt;span class="c"&gt;# List all goroutines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delve integrates with VS Code's debug panel, so you can set breakpoints and inspect state visually without touching the CLI.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. &lt;code&gt;golangci-lint&lt;/code&gt; — Unified Linting
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;golangci-lint&lt;/code&gt; runs multiple linters in parallel under a single binary. It includes &lt;code&gt;staticcheck&lt;/code&gt;, &lt;code&gt;errcheck&lt;/code&gt;, &lt;code&gt;gosec&lt;/code&gt;, &lt;code&gt;gocritic&lt;/code&gt;, and many others. Running each separately would be slow and painful — this bundles them efficiently.&lt;/p&gt;

&lt;p&gt;Configure it via &lt;code&gt;.golangci.yml&lt;/code&gt; at the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;linters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;errcheck&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gosimple&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staticcheck&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;unused&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;govet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the standard linting tool used in professional Go CI pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. &lt;code&gt;air&lt;/code&gt; — Live Reload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/air-verse/air@latest
air
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;air&lt;/code&gt; watches your project for file changes and automatically rebuilds and restarts your application. Essential for web server or API development where you'd otherwise be manually stopping and restarting on every change.&lt;/p&gt;

&lt;p&gt;Configure it via &lt;code&gt;.air.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
  &lt;span class="py"&gt;cmd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"go build -o ./tmp/main ."&lt;/span&gt;
  &lt;span class="py"&gt;bin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./tmp/main"&lt;/span&gt;
  &lt;span class="py"&gt;include_ext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. &lt;code&gt;go mod&lt;/code&gt; — Module and Dependency Management
&lt;/h2&gt;

&lt;p&gt;Go modules are the built-in dependency management system, introduced in Go 1.11 and now the standard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init github.com/username/myapp  &lt;span class="c"&gt;# Initialize module&lt;/span&gt;
go get github.com/some/package         &lt;span class="c"&gt;# Add dependency&lt;/span&gt;
go mod tidy                            &lt;span class="c"&gt;# Remove unused, add missing&lt;/span&gt;
go mod vendor                          &lt;span class="c"&gt;# Vendor dependencies locally&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependencies are declared in &lt;code&gt;go.mod&lt;/code&gt; and locked with checksums in &lt;code&gt;go.sum&lt;/code&gt;. No separate package manager, no &lt;code&gt;node_modules&lt;/code&gt;-style chaos.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting It All Together: A Practical Workflow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# During development&lt;/span&gt;
air                          &lt;span class="c"&gt;# Live reload running in background&lt;/span&gt;

&lt;span class="c"&gt;# Before committing&lt;/span&gt;
go &lt;span class="nb"&gt;fmt&lt;/span&gt; ./...                 &lt;span class="c"&gt;# Format&lt;/span&gt;
go vet ./...                 &lt;span class="c"&gt;# Static analysis&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-race&lt;/span&gt; &lt;span class="nt"&gt;-cover&lt;/span&gt; ./...   &lt;span class="c"&gt;# Tests with race detection and coverage&lt;/span&gt;
golangci-lint run ./...      &lt;span class="c"&gt;# Lint&lt;/span&gt;

&lt;span class="c"&gt;# Building for production&lt;/span&gt;
&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 go build &lt;span class="nt"&gt;-o&lt;/span&gt; bin/myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run without producing a binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compile to a static binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go fmt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enforce standard code formatting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go vet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Static analysis for common bugs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run tests, coverage, race detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gopls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Language server for editor intelligence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;dlv&lt;/code&gt; (Delve)&lt;/td&gt;
&lt;td&gt;Debugger with goroutine awareness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;golangci-lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unified multi-linter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;air&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Live reload during development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go mod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Module and dependency management&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Go's tooling is opinionated by design — and that's a feature, not a limitation. The less time you spend configuring your environment, the more time you spend building. Master these tools early and they'll stay with you throughout your Go career.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Suggested Dev.to tags: &lt;code&gt;#go&lt;/code&gt; &lt;code&gt;#golang&lt;/code&gt; &lt;code&gt;#devtools&lt;/code&gt; &lt;code&gt;#beginners&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>devtools</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
