Go by Example: Generics

Go does not have native support for generics, but you can achieve similar functionality using interfaces and type assertions. Here’s an example that demonstrates how to implement a generic Max function that finds the maximum value in a slice of any comparable type:

package main

import "fmt"

func Max(data []interface{}) interface{} {
    var max interface{}
    for i, item := range data {
        if i == 0 || item.(int) > max.(int) {
            max = item
        }
    }
    return max
}

func main() {
    data := []interface{}{1, 2, 3, 4, 5}
    fmt.Println("Max:", Max(data))
}

In this example, we define a function Max that takes a slice of interface{} values as input. Because interface{} is an empty interface, it can hold values of any type.

Inside the Max function, we loop over the data slice and use type assertions to compare each item with the current max value. If the current item is greater than the max value, we update the max value.

In the main function, we create a slice of interface{} values and pass it to the Max function. The function returns the maximum value, which we print to the screen.

The output of this program will be:

Max: 5

While this approach works, it has some disadvantages compared to a true generics implementation. For example, the type of the Max function’s return value is always interface{}, which means you have to use type assertions to access its value. Also, because the function is not type-safe, it can lead to runtime errors if the slice contains values of different types.

Another example that demonstrates how to implement a generic Swap function that swaps the values of two variables:

package main

import "fmt"

func Swap(a, b interface{}) (interface{}, interface{}) {
    return b, a
}

func main() {
    a := 1
    b := 2
    a, b = Swap(a, b).(int, int)
    fmt.Println("a:", a)
    fmt.Println("b:", b)
}

In this example, we define a function Swap that takes two interface{} values as input.

Inside the Swap function, we simply return the values of b and a in reverse order.

In the main function, we create two variables a and b, and pass them to the Swap function. We use type assertions to assert the return values as ints. Then, we print the values of a and b to the screen.

The output of this program will be:

a: 2
b: 1

As you can see, the Swap function correctly swaps the values of a and b. However, this approach is not as efficient as using a version of the Swap function that’s specialized for each type you want to use it with.

For a real-world example, you could write specialized versions of the Swap function for int, float64, and string types. This would make your code more efficient and easier to maintain.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *