When I joined, a few of us who had recently come in would skip the daily standups. Clock in, clock out, heads down. The rest of the team wasn’t sure what we were working on. This went on for a while. We were reading the existing codebase and quietly rewriting pieces in Go – proving it could handle production before anyone had to commit to it.
That changed when Go got formally introduced. The direction came from above – Go was the language for the new services. Now it wasn’t a side experiment, it was the stack. And the PRs were coming in faster than anyone could review them all.
How people learned
There was no boot camp. No formal training program. No guru-student setup. The engineers could read and learn on their own – Go’s documentation is good and the language is small enough to pick up in a few weeks. What they needed from us wasn’t syntax. It was design.
I was working across several service teams. Engineers would come with questions – not “how do I write a for loop in Go” but “how should this service handle retries” or “should this be a goroutine or a synchronous call.” The conversations were about tradeoffs, not tutorials.
We shadowed each other’s work. I’d review their code, they’d read mine. The learning happened in pull requests more than in any document. When someone made a design choice I disagreed with, we’d talk through the alternatives. When they made a choice I hadn’t considered, I’d learn something too.
Every few weeks we’d run a sharing session for the wider team – design patterns, concurrency approaches, things we’d figured out across the services. These weren’t lectures. More like “here’s what we ran into, here’s how we solved it, here’s why.”
What surprised me
Most of the team wasn’t coming from Perl. The monolith was Perl but the engineers were mostly from Java or other modern languages. They didn’t need to unlearn Perl – they needed to learn Go’s way of doing things they already understood conceptually. Error handling without exceptions was the big adjustment. Concurrency with goroutines instead of thread pools took some getting used to. The interface system clicked faster because people stopped trying to build class hierarchies and just wrote the methods they needed.
The people who picked it up fastest weren’t necessarily the strongest engineers. They were the ones who were curious about the language itself, not just using it to get work done. They’d read the standard library source code, try things in the playground, come back with questions that showed they’d been thinking about idioms rather than just getting something to compile.
I had people from manual QA transition into developer roles through this process. They started by writing test utilities in Go, then small services, then full features. The language was accessible enough that the barrier was motivation, not background.
The style guide question
Go has strong universal idioms. gofmt handles formatting. The standard library sets the tone for naming and package structure. We didn’t write our own style guide from scratch – we made sure everyone understood the existing conventions and the reasoning behind them.
What we did document was design decisions specific to our services. How we structured handlers. How we managed database connections. How we approached error wrapping. These went into an engineering wiki that everyone contributed to. It grew as people encountered patterns and wrote them down. The wiki was a side effect of the work, not a prerequisite for it.
The role
The architects – a few of us – set direction and shaped design. The engineers built the services. The success was theirs. We were enablers, available for the hard questions, staying out of the way for everything else.
Release confidence
The real reason Go works for a growing team isn’t the syntax or the goroutines. It’s that the compiler won’t let you be sloppy. In Node.js – which I used for years and still respect – an unchecked runtime error in a corner case makes it to production. You find out when it panics at 2x traffic. The codebase is efficient and fast to prototype but becomes unpredictable as the team grows. Every release carries a background anxiety.
Go doesn’t allow that. Someone who joined last week can contribute to the next production release and I’m not worried. Not because I’ve reviewed every line – I can’t, there are too many PRs across too many services. But the compiler is the first reviewer. If the build passes, a whole class of mistakes is already gone. The code still goes through review, QA, the usual rituals. But the baseline confidence is different. The compiler catches what a tired reviewer would miss.