How to assess · For hiring teams
How to Assess Go Skills When Hiring
The test formats that actually work for Go, what a strong answer looks like, sample questions and a scoring rubric you can use as-is.
The short answer
Assess Go with a task, not a conversation: concurrency task with a stated failure mode, refactor non-idiomatic go, ai-scored assessment (e.g. cohesyve) or design conversation: a service under load. Score it against written criteria you fix before you see any submissions, and weight the criteria that the role actually depends on.
- Handles every error at the point it occurs, wraps with context, and can explain when to return versus log
- Uses goroutines with a clear lifetime: a way to stop them, and a `sync.WaitGroup` or context to know when they are done
- Reaches for channels when communicating and mutexes when protecting state, and knows which is which
- Defines small interfaces where they are consumed, not where the type is declared
Paste a job description; Cohesyve generates a role-specific assessment and rubric. Ten candidates free, no card.
Go is a small language, which is exactly why it is a good one to test: there is nowhere to hide. A candidate either handles errors properly or ignores them, either understands goroutines and channels or writes code that deadlocks or leaks, either designs interfaces at the point of use or copies Java into Go. The idioms matter more than in most languages because the team will read every line. This page covers how to assess Go for backend and infrastructure roles: concurrency, error handling, interface design and the practical judgement that separates idiomatic Go from a translation.
Why Go is worth testing
Go's simplicity means weak Go is obvious to a Go engineer and invisible to everyone else. A hire who writes non-idiomatic Go — panics for control flow, goroutines with no way to stop, interfaces with fifteen methods — slows a team down at every review and introduces the concurrency bugs Go was supposed to prevent. Testing catches the difference in an hour; discovering it in production takes months.
What strong Go looks like
- Handles every error at the point it occurs, wraps with context, and can explain when to return versus log
- Uses goroutines with a clear lifetime: a way to stop them, and a `sync.WaitGroup` or context to know when they are done
- Reaches for channels when communicating and mutexes when protecting state, and knows which is which
- Defines small interfaces where they are consumed, not where the type is declared
- Uses `context.Context` for cancellation and deadlines through the call chain
- Writes table-driven tests and benchmarks without prompting
- Reads `go vet` and the race detector output and treats them as required
Ways to assess Go
Concurrency task with a stated failure mode
Ask for a worker pool that processes jobs from a channel with N workers, stops cleanly on cancellation, and reports errors without losing them. Forty-five to sixty minutes. Run it with `-race`.
Pros
Cons
Best for Mid and senior backend and infrastructure engineers.
Refactor non-idiomatic Go
Provide a working file written like Java — a large interface, getters and setters, panics on error, a goroutine with no stop. Ask them to make it idiomatic and explain each change.
Pros
Cons
Best for Roles where code review and mentoring matter.
AI-scored assessment (e.g. Cohesyve)
Generate a Go task from the job description — a concurrency design, a refactor, or an error-handling review — with a rubric. Each candidate receives a different variant; explanations are scored with the code.
Pros
Cons
Best for Screening a large pool before engineer time is spent.
Design conversation: a service under load
Describe a service that must fan out to five downstreams with a 200ms budget and degrade gracefully. Ask how they would structure it in Go.
Pros
Cons
Best for Senior engineers and tech leads.
Cohesyve
Run a Go assessment on your next opening
Cohesyve generates a unique Go task per candidate from your job description, with the scoring rubric attached. Questions are different for every applicant, so they cannot be shared or looked up.
What to test
Concurrency
Whether goroutines are safe, bounded and stoppable.
Error handling
Whether errors carry context and reach the right place.
Interfaces and structure
Whether the code is shaped the way Go code should be.
Testing and tooling
Whether they use the tools the language gives them.
Sample Go questions
What is wrong with ignoring an error with `_`? When, if ever, is it fine?
EntryLook for Understands silent failure; can name the rare legitimate cases (e.g. `Close` on a read-only file) and says they would comment them.
Write a function that runs five HTTP calls concurrently and returns when all finish or the context is cancelled.
MidLook for WaitGroup or errgroup, context passed through, results collected safely, no leaked goroutines on cancel.
When would you use a buffered channel, and what goes wrong if the buffer is sized badly?
MidLook for Decoupling producer and consumer; too small blocks, too large hides backpressure and grows memory.
A service occasionally deadlocks under load. How do you find it?
SeniorLook for Goroutine dump via signal or pprof, looking for goroutines blocked on channel ops or locks, reproducing with the race detector and load.
How do you design a package API so that it is hard to misuse?
SeniorLook for Small interfaces, constructors that validate, zero values that are useful, options pattern where needed, unexported internals.
Red flags
- Uses panic for expected errors
- Starts goroutines with no way to stop them or know they finished
- Declares large interfaces up front "for flexibility"
- Has never run the race detector
- Writes Go that reads like another language, with getters, setters and inheritance workarounds
Scoring rubric
| Criterion | Weight | What strong looks like |
|---|---|---|
| Concurrency safety | 30% | Goroutines are bounded, stoppable and race-free; channels and locks are used appropriately. |
| Error handling | 25% | Errors are handled where they occur, wrapped with context, and classified correctly. |
| Idiomatic structure | 20% | Small interfaces, clear packages, useful zero values. |
| Testing and tooling | 15% | Table-driven tests, race detector, vet, benchmarks where relevant. |
| Design reasoning | 10% | Explains timeout, cancellation and degradation choices clearly. |
Mistakes hiring teams make
- Testing algorithm puzzles instead of concurrency and error handling
- Not running submitted code with `-race`
- Accepting "it works" for a goroutine that can never be stopped
- Scoring on speed rather than on the explanation of trade-offs
- Assuming strong Java or C# experience transfers directly to idiomatic Go
Roles that need Go
Common questions
What is the most important thing to test in Go?
Concurrency and error handling, together. Most production Go bugs are a goroutine that leaks or deadlocks, or an error that was ignored or lost. A single worker-pool task with cancellation covers both.
Can a strong developer in another language pick up Go on the job?
The syntax, yes, within days. The idioms take longer and the concurrency model is where people get hurt. If the role is Go-heavy, test Go specifically rather than assuming transfer.
How long should a Go assessment be?
Forty-five to sixty minutes for a concurrency task is enough to see the important things. Take-homes should be capped at two hours; Go is compact enough that longer is unnecessary.
Should I test knowledge of the standard library?
Lightly. Knowing `context`, `sync`, `errors`, `net/http` and `testing` well matters; memorising the rest does not. Let candidates use documentation.
Cohesyve · Skill assessments for hiring
Test Go before the first interview
Generate a role-specific Go assessment from your job description and see who can do the work before you spend interview time on them.
1,500+
assessments completed
50%
faster time-to-hire
90%
completion rate
5 min
from JD to assessment
No credit card · 10 free candidates · Plans sized to your hiring volume
From the blog