I'm a Full-Stack Developer who's actively working full-time and looking for new opportunities. I Love to learn and explore the coding world :'D #golang
A change has been made to the Go language.
We can now use 'for range(n)' similar to Python.
This is a preview feature in Go 1.22. You can try it out by enabling it with 'GOEXPERIMENT=rangefunc'.
Try it: https://t.co/Xy44M5delo
Return early, return often
One of the idiomatic practices in #golang programming is the concept of "return early, return often."
Rather than deeply nesting code, which can lead to "arrow code" shape, Go encourages developers to handle conditions (especially errors) and return as soon as possible.
This makes code more readable, reduces cognitive load, and makes it more maintainable.
Instead of:
consider:
Always check for errors immediately, and return if you need to:
break out of loops quickly:
This is a small change to make, but can make a big difference as your codebase gets much larger.
web development in Canada isn't too much different from the US
we just use "visibleEh" instead of "isVisible" and instead of state it's province management
Singleflight
Singleflight is a really interesting package that "provides a duplicate function call suppression mechanism."
Why use singleflight?
Consider an application that fetches data from an API or a database (i.e, pretty much any application in existence). If several requests trigger the same call, this might trigger multiple identical database or API calls.
These redundant requests can strain your system, leading to wasted CPU cycles, memory, and bandwidth.
By using singleflight, we can remove these duplicate calls really easily.
Here's an example:
In this example, even though we have 5 goroutines simultaneously requesting data for the same key, the fetchData function will only be called once due to the https://t.co/LyQvGCbEhg function from singleflight.
Do you use singleflight? what for?
New Blog Post From the @golang team: Fixing For Loops in Go 1.22
You can read the original blog post here: https://t.co/Z46akYL1Cf, summary below.
The problem
The below should print a,b,c right?
It will actually print c,c,c. This is due to https://t.co/ELHfLEq4oq
Its also possible to face this issue without concurrency:
In Go 1.22, the Go team are changing for loops to have per iteration scope instead of per loop scope.
This is kind of a big change, so this will only apply to go programs that declare go 1.22 in their go.mod file, or use the GOEXPERIMENT=loopvar environment variable.
Google have been running this change in production since May 2023 and have yet to see any issues with it.
Another great milestone and another great blog post by the Go team!
Why Context Should Probably Be the First Argument in Most of Your Go Functions
In #golang, the context package plays a big role in controlling the lifecycle of your code, especially when it comes to handling timeouts, cancellation signals, and passing request-scoped values. If you're designing APIs, it's a common convention to pass the context.Context (named ctx) as the first argument. Here's why:
1. Consistency Across the Go Ecosystem. One of the core philosophies of Go is simplicity and predictability. When different libraries and applications follow the same convention, it reduces the cognitive load on developers. By always passing context as the first argument, we ensure that Go developers instantly recognize the pattern, making the codebase more readable and maintainable.
2. Propagation of Values. The context package not only provides cancellation signals but also a way to store and retrieve values in a safe manner. By consistently passing it as the first argument, you ensure that any nested functions or methods called within have access to these values, ensuring data like request ID and other essential metadata can be seamlessly propagated. This becomes really important for getting things like tracing working.
3. Allows for graceful degradation during slow or unresponsive service calls. By proactively managing delays, the user experience remains controlled, avoiding potential system-wide disruptions. A well-structured context approach can be the difference between a minor issue and a major outage.
Just Build Something!
It might seem counterintuitive, but one of the the best ways to grow as a software Engineer, even if you want to specialise in Backend or #golang, is to build full stack side projects, especially if it means using other languages.
Why?
Every language has its own quirks, patterns and paradigms that you can learn from. For example I have been writing a lot of Typescript lately and the eco-system is entirely different to Go. However, it also enables things that are not possible using Go (such as building mobile apps).
It will also make you a better colleague. After you have battled with some problems in the frontend space, you'll have much more empathy for that team at work.
Finally, I find a lot of the learnings happen in the last mile when you come to deploy your idea and make it available beyond your laptop.
I don't know what to build :(
This is another chance to flex a different skillset. I keep a running set of notes on my phone where I write down problems I have (even really really minor ones). I then will come up with solutions for them and build them! I don't worry about the fact that solutions likely already exist because that's not the point. Not all side projects need to be commercially viable and not all side projects need to be useful to anybody but you.
For me, the key signal of a good side project is when I think to myself "hmm, I'm not sure how I'll do that". or "hmm I'm not sure how that will work". This unknown is where the real learnings are.
Here are some of the problems I have written down in the past few months and the solutions I have built. As you can see they are all fairly simple. If you are struggling for ideas, feel free to steal mine.
Problem: I forgot to take an umbrella and it rained
Solution: I wrote a telegram bot that messages every morning and tells me if I should take an umbrella or not based on the Weather.
Problem: I wanted a product that was always out of stock.
solution: I wrote a web scraper that checks to see if its in stock and if so, adds it to the basket and checks out.
Problem: My friends and I wanted to do a Fantasy football league for the women's World Cup but none of the apps had the rules we wanted.
Solution: Built my own app.
Problem: My website went down and someone had to email to tell me
Wrote a small program to check it on an interval from various locations globally and email me if its down.
If you want to dive a bit deeper into this, @levelsio is amazing at ideation and shipping. He had no prior programming experience and has built some incredibly cool products. His book digs into his process more and I highly recommend it (https://t.co/IMtY89wYaK). His focus is on how to build income, but I think a lot of his advice is great for people learning too. I'm sure you wouldn't be mad if you made an income stream from it though :)
Go Build Tags
Did you know you can include comments #golang in files that determine whether a file should be included during the build process?
For example, the following simple code:
will be excluded from builds except on Linux, unless we explicitly pass the build flag.
You can also achieve this with file naming, for example a file called run_linux.go with no build tag would achieve the same behaviour.
One way I like to use build tags is to divide my tests up. Perhaps my integration tests need docker to be running, or are just generally much slower to run. I want to keep them separate from my unit tests which run rapidly and I run them often. I can do something like the below:
and then my tests only run when I run:
go test -tags=integration.
If I don't pass the tag, it only runs tests not tagged, which are my unit tests.
What do you use build tags for?
Today, Learn Go with Tests reached 20 thousand⭐️ on GitHub!
Stars are a silly vanity metric, but I'm still very jazzed.
Wrote a thing here reflecting on the past 5 or so years
https://t.co/Y0vEoCRQgh
https://t.co/622inKlOPk #golang#tdd
Here's a cool little #golang trick. You can add something like the following:
to the top of your code to force a compile time check that a struct satisfies an interface. If it doesn't you'll see an error such as:
You shouldn't need to do this all the time, but let me tell you why it can be useful.
In #golang , interfaces are implicit. This means you do not have to declare that a type implements an interface. By adding the above, you are making it 100% clear that it is your intention that SomeType implements SomeInterface. It also helps with auto-complete in IDEs, and guards against breaking changes.
Here is another, more concrete example from Uber's style guide:
Do you use this? what other little tricks do you use?
Backwards Compatibility, Testing Changes to the Go Language and GODEBUG
Yesterday a blog post by @_rsc was released on https://t.co/yzwyP7mFnd. The post is well worth a read but here is a summary of my key takeaways:
- The #golang team takes backwards compatibility really seriously, and will continue to even as Go 2.0 gets created. A go 2.0 program should never break a Go 1.0 program.
- Backwards compatibility is incredibly nuanced. The best example of this is that they wanted to improve the precision of https://t.co/dgkOa7XGDJ() but it broke some tests that look like this at Google. They therefore had to take a different approach.
- Whenever a new Go release is created, they test it against the entire Google codebase and use that as an indicator of whether there is any breaking changes. They have also built custom tooling that ensures they never remove exported APIs.
- The Kubernetes team and the Go team work closely together to ensure that any nuances to changes are considered.
- When a new version of Go is ready, Google use it as their production version before the public release.
- If any of the changes the Go team has made does break your code, GODEBUG (https://t.co/PrXsLCdIbg) was formalised in Go 1.21 which means you can essentially "opt-out" of the behaviour changes.
My Take
The Go team being inside Google gives such a large benefit to the #golang community and this post really helps you to understand that. Having the k8s team work so closely with them and having the benefit of one of the largest Go code bases in existence to run tests against is why we get such successful releases regularly.
Thanks for the insight @_rsc