Getty Images/iStockphoto

Tip

What Golang generics support means for code structure

Generics are a relatively recent addition to the strongly and statically typed Go language. Learn the benefits of using generics in Golang and how to get started.

Go, also known as Golang, is a compiled programming language that is considered strongly and statically typed. The language added generics support in March 2022, an update that has the potential to simplify a project's overall codebase.

But before diving into Golang generics, programmers must understand Go's type system and how it fits into the overall programming language universe.

Strongly typed vs. weakly typed programming languages

Strongly typed programming languages only allow operations on certain variable types. For example, a strongly typed language would not allow an integer to be added to a string because the language deems the two data types incompatible.

A weakly typed language, in contrast, would automatically convert one of the variables to the other type and perform the addition.

As an example, consider the following line of Go code.

var s = "1" + 1

Because the types are mismatched -- "1" is a string and 1 is an integer -- the addition operation cannot be performed. Instead, the compiler returns the following error.

invalid operation: "1" + 1 (mismatched types untyped string and untyped int)

Compare this output with the results of the same operation in JavaScript, a weakly typed language.

console.log("1" + 1)

This returns the string "11" because JavaScript converts the integer to a string to concatenate the two values. JavaScript does not hold a strong definition of provided data types and instead casts them implicitly.

The question of whether a language is strongly or weakly typed isn't always straightforward. No language is 100% strongly or weakly typed, as features can be individually strongly or weakly typed.

For the most part, Go is described as strongly typed for the reason shown above. However, there are examples of weakly typed features in Go. Specifically, Go interfaces are implemented implicitly, without any implements keyword. If a type implements methods defined by an interface, then it implements that interface automatically.

Statically typed vs. dynamically typed programming languages

Static and dynamic typing describe whether a programming language checks a variable's type at compile time or runtime. A common misconception is that all strongly typed languages are statically typed and, likewise, all weakly typed languages are dynamically typed.

The infographic displays the stages of the programming lifecycle.
Statically typed languages check a variable's type early in the programming lifecycle, at compile time, whereas dynamically typed languages can update type at runtime.

Go is statically typed and therefore cannot update a variable's type at runtime. Consider the following example.

var s = "Hello, World" 
s = 2

Upon running this code, Go's compiler fails and returns the following error.

cannot use 2 (untyped int constant) as string value in assignment

Because the variable s is statically typed as a string, it can only be updated with string values.

The following is an example of type reassignment in Python, a dynamically typed language where these lines cause no issue in execution.

i = 4 
i = "four"

What are generics in programming?

From a general programming perspective, generics are functions or data structures that can be written without defining specific types. With generics, it's possible to write a function that accepts a generic type and can be called on many different types.

As an example, imagine writing a function to reverse a list of integers. In a language without generics, a programmer would need to write a separate function for each type of list. The program would require separate reverse functions to handle a list of integers, a list of strings and a list of lists.

The goal of generics is to reduce duplicated code that arises when the same functions are performed on different types. Instead of defining separate reverse functions for lists of integers and lists of strings, generics allow programmers to define a function for a generic type, which can then be called on a list made up of values of any type.

Golang generics

For most of Go's history, the language did not support generics. Go's creators and lead engineers were initially concerned that the addition of generics would create unnecessary complexity or lead to slower programs. Generics, an influential addition to the language, were introduced in March 2022.

Below is an example of present-day Go generics in action.

func reverse[T any](myList []T) []T {
    length := len(myList)
        reversedList := make([]T, length)
        for index, element := range myList {
            reversedList[length-index-1] = element
        }
        return reversedList
    }
    func main() {
        primes := []int{2, 3, 5, 7, 11, 13}
        names := []string{"Jack", "Frank", "Petra", "Harlod"}

        fmt.Println(reverse(primes))
        fmt.Println(reverse(names))
    }

The generic function's signature includes the any keyword, which specifies that T -- our generic type -- can be any type. To specify that the function can only be used with certain types, such as strings and integers, write those types in place of the any keyword. For a function that sorts a list, using the Ordered keyword restricts the function to types that can be compared using the >, >=, < and <= operators.

Next Steps

Follow a Kubernetes and Go tutorial in your home lab

Dig Deeper on DevOps