AI code review for Go —
catches error-swallowing + goroutine leaks.
Go's simplicity is a feature until it hides bugs. Discarded errors (`_, _ := ...`), goroutines that outlive their context, panics used as control flow, string interpolation in database queries. LGTM's Go hints fire in the bugs + performance agents whenever it sees `go.mod` in your repo.
Auto-detected. Zero configuration.
Auto-detected when `go.mod` exists in your repo root. LGTM's Go hint pack loads into the bugs + performance + best-practices agents automatically.
Go bugs that hide in plain sight
Four patterns that get past general-purpose code review because they look like idiomatic Go. LGTM knows the shape of each.
Swallowed errors
`result, _ := someCall()` discards the error. Reviewers glance past it because the code compiles and often works. Until it doesn't — the discarded error was the only signal something went wrong.
Goroutine leaks
`go doThing()` with no context cancellation, no wait group, no way to stop the goroutine when the parent exits. Long-running services accumulate leaked goroutines that hold memory + connections forever.
panic as control flow
Go idiom is 'errors are values, not exceptions'. `panic()` is for genuinely unrecoverable state. Using it to bail out of a function because handling the error is annoying is anti-idiomatic and creates upstream crash sites.
database/sql string interpolation
`db.Exec(fmt.Sprintf("SELECT * FROM u WHERE id = '%s'", id))` is SQL injection. The `Exec` and `Query` methods take variadic args for a reason: `db.Query("SELECT ... WHERE id = $1", id)`. Easy to reach for Sprintf when the parameter placeholder syntax is unfamiliar.
What LGTM actually catches
Three real examples — the Go-aware bugs + security agents flag these with inline 🎯 Actionable comments and a clear "why" explanation.
func getUser(db *sql.DB, id string) (*User, error) {
row := db.QueryRow(fmt.Sprintf(
"SELECT id, email FROM users WHERE id = '%s'", id,
))
// ...
}What: fmt.Sprintf building a SQL query from a user-supplied id
Why: Even if id looks like it comes from a trusted source, one refactor later it's from an HTTP request. Use parameter placeholders: `db.QueryRow("SELECT id, email FROM users WHERE id = $1", id)`.
func writeLog(msg string) {
f, _ := os.OpenFile("app.log", os.O_APPEND|os.O_WRONLY, 0644)
defer f.Close()
f.WriteString(msg + "\n")
}What: os.OpenFile error discarded — nil dereference on the very next line
Why: If OpenFile fails (permission denied, disk full), `f` is nil and `f.Close()` / `f.WriteString()` will panic. Handle the error: `if err != nil { return err }`, then use `f`.
func startBackgroundSync(user *User) {
go func() {
for {
syncOnce(user)
time.Sleep(1 * time.Minute)
}
}()
}What: Goroutine spawned with no context or shutdown mechanism
Why: This goroutine runs forever — even after the User is deleted, the request is done, or the service tries to shut down gracefully. Accept a `ctx context.Context`, `select` on `ctx.Done()`, exit cleanly.
Go starter .lgtm.yml
Skip vendored deps + generated protobuf, force the go framework slug, bump SQL + goroutine-leak + unhandled-error to critical.
version: 1
paths:
- pattern: "vendor/**"
skip: true
- pattern: "**/*.pb.go"
skip: true
- pattern: "**/*_generated.go"
skip: true
frameworks:
- "go"
severity_overrides:
sql-injection: "critical"
goroutine-leak: "critical"
unhandled-error: "high"
auto_approve_docs_only: true
Commit as .lgtm.yml at your repo root, flip the Enable .lgtm.yml toggle in Repo Settings. Next PR picks it up. See all recipes →
What ships on every Go review
Same pipeline that reviews everything else on LGTM — the Gohints just tune each agent's attention.
6 agents in parallel
Bugs, Security, Performance, Readability, Best-practices, Documentation. Each with framework-specific hints when LGTM detects your stack.
16 CI/CD detectors
LGTM Security scans your GitHub Actions, Dockerfiles, and lockfiles alongside the code review. Merge-blocking Check Run on block-level findings.
Adversarial verifier
Every finding is refuted by a skeptic LLM before it posts. Only survivors reach your PR. Kills the confident-hallucination class of false positives.
Try LGTM on your Go repo
Free tier: 20 reviews / month, all 6 agents, all 16 security detectors. BYOK OpenAI or Anthropic. No card required.