# GoConc Desk > Audit the concurrency in Go code before it ships - will it race, deadlock or leak goroutines - then fix it. The free check runs in the browser and uploads nothing: it lexes pasted Go (one or more files, plus go.mod for the Go version), matches every brace, inventories every function, goroutine (go statements and errgroup Go), loop, select, channel, Lock/Unlock pair, WaitGroup, derived context and HTTP handler, and runs 23 deterministic checks drawn from Go concurrency practice. The paid audit rates goroutine lifecycle, shared state, channels and cancellation, confirms or dismisses every flag and gives exact before/after edits per finding; the paid fix lane writes the whole fixed file(s) and a changes list tied to the flags. The page checks every quote and line against the paste, applies every edit and file back into the paste and re-runs its checks, and calls out a reply that repeats a credential from the paste. App: https://goconc-desk.skillsafe.ai/ API tutorial: https://goconc-desk.skillsafe.ai/api.html ## Input - The code pasted into one box, each file introduced by a `// file: ` line; dropped files or a dropped package folder are joined that way automatically. A paste with no `// file:` line is read as one file (main.go). go.mod, when pasted, gives the Go version (loop variable semantics changed in Go 1.22). - Nothing is compiled or run, and this is not the race detector: every flag is a reading of the text, with the file and line it points at. Strings, runes and comments are lexed out first, so a string that mentions go func( or mu.Lock() is never a finding. - A close, Unlock or Wait in a file that was not pasted is outside the check (GC-24 says so); `go test -race` stays the ground truth. ## Flags the free check raises - GC-01 (high when go.mod says 1.21 or earlier, low when go.mod is not pasted): a loop variable read by a goroutine started in the loop. - GC-02 (high): WaitGroup.Add inside the goroutine it counts - Wait can return early. - GC-03 (high): a goroutine that never calls Done after Add - Wait never returns; (medium) an early return that skips a non-deferred Done. - GC-04 (high): a sync.WaitGroup, Mutex or RWMutex passed by value, or a value receiver on a struct holding one that locks it; (medium) a value receiver that only copies it. - GC-05 (high): Lock or RLock never released in the function; (medium) a return, break or continue between Lock and a non-deferred Unlock. - GC-06 (high): an RLock released with Unlock, or a Lock with RUnlock. - GC-07 (high): a map written from goroutines started in a loop, errgroup goroutines, or an HTTP handler (package-level map or server field), with no lock. - GC-08 (high): a shared variable updated (++, +=) in the same places with no lock or atomic. - GC-09 (high): a variable updated with sync/atomic but read or written plainly elsewhere. - GC-10 (high): a goroutine sending on an unbuffered channel that a select with a timeout or ctx.Done() case may stop reading - one leaked goroutine per call. - GC-11 (high): for ... range over a channel made in the paste that nothing in the paste closes. - GC-12 (high): close(ch) inside a goroutine started in a loop - the second close panics. - GC-13 (medium): a goroutine running a bare for loop with no return, break, done channel or ctx.Done(). - GC-14 (medium): a select with an empty default inside a loop - a busy spin. - GC-15 (high): a cancel func from context.WithCancel/Timeout/Deadline discarded (_) or never used. - GC-16 (medium): context.Background() or TODO() in a function that already has a ctx parameter or a request. - GC-17 (medium): a goroutine started in an HTTP handler that uses the request or its context. - GC-18 (medium): go f(...) where f, in the paste, returns an error. - GC-19 (low): one goroutine per item of a range loop, with no SetLimit, semaphore or pool. - GC-20 (low): time.After inside a select in a loop. - GC-21 (low): a time.NewTicker never stopped, or time.Tick outside main. - GC-22 (low): time.Sleep after starting goroutines, in a function that never waits for them. - GC-23 (low): a context.Context stored in a struct field. - GC-24 (info): context - counts, the Go version, what is outside the check. ## Free extras - Every goroutine with where it starts, its kind and whether it is in a loop; every channel with its buffer and whether the paste closes it; every Lock with how it is released; every derived context with what happens to its cancel func. - Put any audit finding (or all of them, or the fixed files) back into the paste and re-run the check; undo puts the original back. An edit whose indentation differs from the file only in tabs versus spaces is matched line by line and re-indented to the file's own tabs. - Exports: the check as Markdown, the flags as CSV, the edited or fixed code, the findings or changes as CSV, the whole result as JSON. ## Paid lanes (the `task` field) - `audit`: `{task, verdict: blocked|needs_work|ready, headline, component, areas: [{area: lifecycle|shared_state|channels|cancellation, status: sound|fragile|broken, note}], findings: [{id, flags, file, line, severity, area, title, evidence, why, edits: [{before, after}]}], flag_answers: [{flag, status: confirmed|dismissed, reason}], plan, questions, summary}`. `before` is an exact slice of the file, applied in order. - `fix`: `{task, verdict: fixed|partial, headline, files: [{path, content}], changes: [{file, function, flags, change, why}], verify, open: [{item, flags, reason}], questions, summary}`. `content` is the whole file. - Run input: `{task, code, facts, note?, audit_handoff?, retry_note?}` - all strings; `facts` is the page's analysis as a JSON string. The audit hands its findings to the fix lane with every edit applied to `code`. - Model: gpt-terra, 10% publisher markup. A run needs a signed-in account; the reservation shown before a run is a hold, and only what the run uses is charged. ## Sources - go-concurrency-patterns by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/systems-programming/skills/go-concurrency-patterns), MIT - https://skillsafe.ai/skill/@wshobson/go-concurrency-patterns - The checks and the reconciliation are original to this app. Go is a trademark of Google LLC; this app is not affiliated with Google or the Go project.