Reader small image

You're reading from  Go Programming - From Beginner to Professional - Second Edition

Product typeBook
Published inMar 2024
Reading LevelBeginner
PublisherPackt
ISBN-139781803243054
Edition2nd Edition
Languages
Right arrow
Author (1)
Samantha Coyle
Samantha Coyle
author image
Samantha Coyle

Samantha Coyle, a Software Engineer at Diagrid, specializes in Go for cloud-native developer tooling, abstracting application development challenges. Committed to Open Source, she contributes to projects like Dapr and Testcontainers. She boasts a rich history in retail computer vision solutions and successfully stabilized industrial edge use cases with testing and diverse deployments for biopharma data pipelines. Her expertise extends to being CKAD certified and reviewing Go textbooks. She is passionate about empowering early-career, diverse professionals. Samantha is in a family of gophers, and enjoys GopherCon with her brother and identical twin sister. She's a seasoned speaker, having presented at various conferences, including GopherCon.
Read more about Samantha Coyle

Right arrow

Generic Algorithm Superpowers

Overview

This chapter will discuss the versatility and expressive strength that Go’s type parameter syntax brings developers. As we explore this chapter, we’ll uncover the means to create algorithms that transcend the limitations of single variable types. By harnessing the power of type parameters, developers gain the ability to craft generic versions of their code, enabling it to seamlessly operate on multiple types. This chapter will highlight the overarching goal to reduce code duplication while preserving the robust safety intrinsic to Go’s strong typing system.

This chapter will also navigate the world of constraints, showcasing how Go fortifies generic algorithms against unintended mishaps, as well as help you understand when to use generic algorithms versus interfaces. Through practical examples and activities, you will grasp the art of designing generic algorithms and understand the superpowers of generic algorithms....

Technical requirements

For this chapter, you'll require Go version 1.21 or higher. The code for this chapter can be found at https://github.com/PacktPublishing/Go-Programming-From-Beginner-to-Professional-Second-Edition-/tree/main/Chapter08.

Introduction

The Go team at Google is always thinking about how to make the lives of Go developers easier and what tools, packages, and support we need for the future – always in a fully backward-compatible way. In this chapter, we will expand upon our knowledge gained so far and discuss Go generics.

Generics officially became a part of the language in Go version 1.18. Go generics provide a powerful means of developing code that removes duplication, simplifies readability, and enables developers a way to use multiple types within a function. However, with great power comes great responsibility. Let’s discuss generics further.

When to use generics?

The decision to finally incorporate generics into the Go programming language was not a trivial one. As they are such a large change to the language, it is important to remember our roots as developers and not to allow support such as generics to change how we write our code. In other words, you should continue writing normal Go code and not overly design types right from the get-go. These are fundamental Go philosophies rooted in simplicity and readability, which are the core tenets of the language.

The following is a synopsis of insights to consider when incorporating Go generics into a code base:

  • Write normal Go code, and don’t design types: Start with your typical concrete types and straightforward functions, leveraging Go’s strong static typing and simplicity. Generics were never meant to replace the fundamental principles guiding the use of the language but, rather, be a tool to be applied judiciously.
  • Avoid boilerplate code...

Type parameters

Type parameters for Go functions give you the ability to parameterize a function with types that support generic input. It’s a way to specify to the compiler the types allowed when invoking a generic function and represents a placeholder for a type within a given function. Type parameter lists look like normal parameter lists but are encompassed by square brackets. For example, [T any] declares a T type parameter that can be any type. The any keyword was touched on in the previous chapter.

To continue to understand type parameters, let’s return to our maximum generic function signature from the earlier example code:

func findMaxGeneric[Num int | float64](nums []Num) Num {

This indicates that our function, titled findMaxGeneric, includes a type parameter, Num, that can be instantiated by an integer or float64 type. It will take in a slice of Num and return the resulting maximum integer or float64 value.

An interesting concept associated with...

Type constraints

Type constraints are a sort of meta-type for the function type parameter. Type constraints dictate the allowed type arguments for any given type parameter of a function.

Type constraints in Go generics refer to interfaces that define sets of types. These interfaces play a powerful role in specifying the requirements or capabilities that a type parameter must satisfy when working with generic functions or types. To use these interfaces effectively, they must be placed in what is known as the “constraint position” within the syntax, specifically in the type parameter list where the type parameter is declared.

In this constraint position, when declaring a generic function or type, the constraints are expressed using an interface type to define the expected behavior of the type parameter. This ensures that the provided types adhere to the specified constraints, allowing the generic code to operate on them safely. By enforcing these constraints, the...

Type inference

The Go compiler infers the types we want to use from the function arguments. This is called type inference. The compiler will deduce type arguments from type parameter constraints.

Type inference either succeeds or fails. The compiler will complain, and we are provided the type arguments that need correcting upon finding an issue. Using generics is meant to be easy; however, the underlying details of type inference are highly complicated. It is also something the authors are iterating on to improve.

At this point, when it comes to calling generic functions, we’ve covered how you can specify type arguments in square brackets as type names. This allows the compiler to know to replace the type parameters within the function you’re invoking. However, you can omit the type arguments, as most of the time Go can infer them. However, it is not always possible to simplify your code by dropping type arguments. As the compiler runs your code, it replaces each...

When to use generics versus interfaces

The question of when to use generics versus interfaces in Go often depends on the nature of the problem you’re solving and the specific requirements of your code.

Generics in Go allow you to write functions or data structures that can operate on a variety of types, without sacrificing type safety. With generics, you can create functions or structures that work with different types, without the need for code duplication and while maintaining compile-time safety checks.

Interfaces in Go define a set of method signatures. Any type that implements all the methods of an interface is said to satisfy the interface. Interfaces provide a way to achieve polymorphism in Go, enabling code to work with different types that share a common set of behaviors. Interfaces are technically a form of generic programming by allowing developers to capture common aspects of different types and express them as methods. This allows for not only a nice abstraction...

What are some best practices?

The following are a few best practices to consider when working with generic code:

  • Use functions over methods: A method is a function associated with a type and is called with a receiver; therefore, a function in the context of generics is more flexible, as it is not tied to a specific type. This allows for easier reuse and the ability to compose functions with different types.
  • Ease of transformation: It is easier to turn methods into functions than it is to add a function to a type. Functions can be defined independently of specific types. In the context of generics, you can use generic functions with any type that satisfies the required constraints. If it later makes sense to convert to a method, then you can do so without modifying the original function more easily.
  • Prefer functions over constraints that require methods: Instead of defining constraints that specifically require a method on a type, prefer using functions that work with...

Summary

In this chapter, we explored the world of Go generics, a groundbreaking enhancement to the language that provides key features such as type parameters, constraints, and type inference. Type parameters, encapsulated within square brackets, emerged as versatile placeholders, enabling the creation of functions and data structures without prior knowledge of the specific types they are to interact with. The incorporation of constraints such as comparable bolstered type safety and clarity, ensures that the generic constructs adhere to specific rules or interfaces. Moreover, the compiler’s type inference unveiled a new era of concise and streamlined code, where developers can leverage static typing without the burden of explicit type annotations.

While Go generics is still being smoothened out and added to, it is a powerful addition that aims to empower developers to write efficient, reusable code with unprecedented ease. Now that we know how to write optimal and reusable...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Go Programming - From Beginner to Professional - Second Edition
Published in: Mar 2024Publisher: PacktISBN-13: 9781803243054
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Samantha Coyle

Samantha Coyle, a Software Engineer at Diagrid, specializes in Go for cloud-native developer tooling, abstracting application development challenges. Committed to Open Source, she contributes to projects like Dapr and Testcontainers. She boasts a rich history in retail computer vision solutions and successfully stabilized industrial edge use cases with testing and diverse deployments for biopharma data pipelines. Her expertise extends to being CKAD certified and reviewing Go textbooks. She is passionate about empowering early-career, diverse professionals. Samantha is in a family of gophers, and enjoys GopherCon with her brother and identical twin sister. She's a seasoned speaker, having presented at various conferences, including GopherCon.
Read more about Samantha Coyle