Now Is The Best Time to Learn Go
Let’s review 3 of the main updates introduced in Go 1.22, and by the end of this article you’ll see that there is no better time than now to learn Go and start enjoying its benefits.
After all, Go shows up in the top 10 programming languages used on GitHub and is seeing a lot of growth across newly created projects. Let’s start with one of the most important updates.
For Loops are Fixed
For loops that share variables across iterations are finally fixed.
To showcase this, let’s create a slice of strings, iterate over it, and start a goroutine which simply prints out the value to the screen. Then, using a buffered channel, we’ll use a second loop to wait for all the async code to finish before closing the program.
func main() {
done := make(chan bool)
values := []string{"a", "b", "c"}
for _, v := range values {
go func() {
fmt.Println(v)
done <- true
}()
}
for _ = range values {
<-done
}
}
This implementation has a small gotcha that caused issues prior to this release. The anonymous functions are executed concurrently and are capturing the “v” value in a closure. Since the execution is likely to happen after all the iterations, the output of this code would probably be this one (c, c, c). This behavior is common in other languages as well, but Go is finally addressing it (output go1.22: c, a, b). Of course, the order of the letters is still not guaranteed since the functions are executed in parallel.
Ranging Over Integers
Next, let’s look at a small quality of life improvement - the support for ranging over integers. Go focuses on simplicity, and it only has one construct to handle looping - the for statement.
for i := 0; i < 5; i++ {
fmt.Println(a...: "Value of i is ", i)
}
j := 0
for j < 5 {
fmt.Println(a...: "Value of j is ", j)
j++
}
for {
fmt.Println(a...: "To infinity and beyond!")
}
You can use it as a traditional for loop, as a while, or as an infinite loop.
languages := []string{"go", "js", "java"}
for _, lang := range languages {
fmt.Printf(lang)
}
You can iterate over collections, and starting with this version, over ranges of integers as well.
for i := range 10 {
fmt.Printf(lang)
}
Methods and Wildcards
Finally, one big improvement especially for web developers is the support for methods and wildcards, when working with the http server.
The standard library is a big thing in Go, and you should always use it over other 3rd party libraries whenever possible.
mux := http.NewServeMux()
mux.HandleFunc("/books", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
// Handle POST requests
} else if r.Method == http.MethodGet {
// Handle GET requests
}
})
if err := http.ListenAndServe(":8080", mux); err != nil {
fmt.Printf("Error: %s", err)
}
However, mapping requests to methods was a bit too tedious prior to 1.22, and people were relying on some other established solutions when building web servers(Fiber, Gin, Echo). The multiplexer patterns are way more powerful and flexible now, so keeping your web app codebase dependency free seems a bit more achievable.
mux := http.NewServeMux()
mux.HandleFunc("GET /books/", func(w http.ResponseWriter, r *http.Request) {
//Show books
})
mux.HandleFunc("GET /books/{id}", func(w http.ResponseWriter, r *http.Request) {
//Show book
})
mux.HandleFunc("POST /books", func(w http.ResponseWriter, r *http.Request) {
//Save books
})
if err := http.ListenAndServe(":8080", mux); err != nil {
fmt.Printf(format: "Error: %s", err)
}
This is far from being a full overview of the language, but the features we looked at should give you an idea about the power and simplicity behind Go.
Until next time, thank you for reading!