Learning Go: January 2026 Review
I spent January learning Go and building three projects: a Japanese kanji Telegram bot, a Claude API proxy with gitleaks integration, and a Kubernetes operator for vLLM load balancing. Documenting what I’ve learnt.
· 3 min read
Jan 2026 #
Summary #
I started learning Go in January and found it to be an interesting language. I can see why it’s utilised more often. The syntax is straightforward, but writing good Go requires solid knowledge of systems programming—like handling race conditions effectively.
Coming from Rust, I noticed that Go’s compile-time checks are looser. This isn’t bad; it just reflects different priorities. Go prioritises iteration speed, and I can definitely say the learning curve is less steep than Rust’s.
What I’ve done #
Some of these projects are in my graveyard and may not be public.
Telegram bot #
This was a mix of AI engineering and Go. I made Kanji Bot, which was a bot that uses the go telegram sdk.
Learning points
- redis go
- reading of json files
- html templating
- qwen3 tts
This also ties in with my other goal to learn a bit of Japanese everyday.
Claude gitleaks #
This repo was sort of an end to end, where I use Go to write a proxy for passing anthropic messages. Additionally, I experimented with goreleaser and renovate to help with CI/CD. I have used gitleaks extensively only as a pre-commit hook but never as a library.
Learning points
- Proxy
- gitleaks
- anthropic go sdk
- CI
vLLM load balancer #
This was an internal experimentation to use Go to write a custom LB for vLLM services. This was sort of the heart of DevOps, developing tools or operators to help with services. It uses the kube sdk to run so that this pod runs together with other services.
What it does is scan all pods in the current namespace for “vllm like” instances, then adds them to a pool. Currently the pool is in memory, and not on a distributed store like Redis. Every second, it checks for the /health and /models endpoint. If it discovers a new pod with these endpoints, it adds them to the pod data.
So imagine you have 3 vllm instances with 3 models, this operator scans your pod endpoints, then adds them to the /models. There is no need to add services to the vllm manifests.
- skaffold dev (for auto pushing)
- kubernetes permissions (RBAC)
Experience #
Ranges #
I took awhile to understand some syntaxes about Go, like how their for works:
for idx := range items
// and
for idx, item := range itemsComing from python, I would think the first item is a Tuple construct of (idx, item). But actually its just the index. This video was interesting as well, it was also not recommended to use idx, item if you need access to any item for reading or mutation. Too early for optimisation, but always good to learn habits.
Channels #
While it took a while as well, I actually loved it a lot.
In rust you had to do
let (sender, receiver) = channel();
// async spawn or thread spawn a producer or consumer task:
thread::spawn(move || {
sender.send(expensive_computation()).unwrap();
});
// do other things here
println!("{:?}", receiver.recv().unwrap());But in go it was really neater:
// create channel for messages
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <- messagesError #
I think this was fine, it was a little annoying with the boilerplate, but I think it becomes habitual.
I personally like rust more for this because of the ? operator.
fn main() -> Result<(), Error> {
do_something()?
}func main() {
res, err := DoSomething()
if err != nil {
log.Fatal(err)
}
}