[SOLVED] Define GO function with multiple types

Is it possible to pass multiple types to GO function?

A golang function can take multiple types of variables as an argument. In this article, we will go over two approaches to writing functions that accept two or more types.

  • If we pass interface types as arguments, we can call the function with any type that implements the given interface.
  • The second method is using generics: before version 1.18, go had nogenerics feature. With generics, you can declare and use functions or types written to work with any set of types provided by calling code.

Generics is a programming technique that is frequently used in OOP (instructional object programming). This technique aids programmers in the definition of functions (methods) that accept generic parameters without specifying the data type. The caller decides to do this until the function is used.

 

Method 1: Using interface types as arguments

We use interface types as arguments in this section. If a type has the interface's methods, Go will automatically implement it. If you want to accept all possible types, you can use an empty interface (interface{}), because all types implement it.

Advertisement

 

Example-1: Go function to accept two different types

This is a very simple example where we have defined two functions which accepts two different types of input wherein A accepts strings while B accepts map of string. Here we will use another function C to accept both the types using an empty interface definition:

package main

import "fmt"

func A(i []string) {
	C(i)
}

func B(i map[string]string) {
	C(i)
}

func C(i interface{}) {
	fmt.Printf("the type was %T\n", i)
}

func main() {
	A([]string{})
	B(map[string]string{})
}

Output:

$ go run main.go
the type was []string
the type was map[string]string

 

Example-1: Go function to accept three different types

In this example we write a function which accepts three different types of input i.e. string, int and float64 using empty interface.

package main

import (
	"fmt"
)

func print_out_input_type(x interface{}) string {
	switch x.(type) {
	//if input is string => print this line
	case string:
		return "This is a string"

	//if input is int => print this line
	case int:
		return "This is an int"

	//if input is float64 => print this line
	case float64:
		return "This is a float64"

	//default value
	default:
		return "default value"
	}
}

func main() {
	fmt.Println(print_out_input_type(12))
	fmt.Println(print_out_input_type("abc"))
	fmt.Println(print_out_input_type(11.04))
}

Output:

This is an int
This is a string
This is a float64

 

Method 2: Using generics

In this section, we will declare a simple non-generic functions, then capture the same logic in a single generic function. The code shown below will find sum of integers and float64 list using 2 non-generic functions.

package main

import (
	"fmt"
)

func main() {
	// Initialize a integer list
	ints := []int{10, 2, 85, 41, 5}

	// Initialize a list for the float values
	floats := []float64{10.2, 21.5, 5.6, 40.5, 6.5}

	fmt.Printf("Non-Generic Sums: %v and %v\n",
		SumInts(ints),
		SumFloats(floats))
}

// sum of int list
func SumInts(m []int) int {
	s := 0
	for _, v := range m {
		s += v
	}
	return s
}

// sum of float list
func SumFloats(m []float64) float64 {
	s := 0.0
	for _, v := range m {
		s += v

	}
	return s
}

Output:

Advertisement
Non-Generic Sums: 143 and 84.3

Now, we will add a single generic function that can receive a list containing either integer or float values, effectively replacing the two functions we just wrote with a single function. 

package main

import (
	"fmt"
)

func main() {
	// Initialize a integer list
	ints := []int{10, 2, 85, 41, 5}

	// Initialize a list for the float values
	floats := []float64{10.2, 21.5, 5.6, 40.5, 6.5}

	fmt.Printf("Generic Sums: %v and %v\n",
		SumIntsOrFloats(ints),
		SumIntsOrFloats(floats))
}

// SumIntsOrFloats calculate sum the values of list m. It can receive both int64 and float64
// as types for int values.
func SumIntsOrFloats[V int | float64](m []V) V {
	var s V
	for _, v := range m {
		s += v
	}
	return s
}

Output:

Non-Generic Sums: 143 and 84.3

Explanation:

Declare a SumIntsOrFloats function with 1 parameter V.

Specify for the V type parameter a constraint that is a union of two types: int and float64. Using | specifies a union of the two types, meaning that this constraint allows either type. Either type will be permitted by the compiler as an argument in the calling code.

 

Summary

Personally, I believe that the addition of generics to the Go language is a significant advancement for the language. On the other hand, it will help to change the way Go developers organize their source code in order to make better use of this functionality. With this feature, we can accept two or more types as function's parameters. Besides that, we can use interface types as arguments in some cases to make our program more efficient and readable.

 

References

https://go.dev/doc/tutorial/generics
How do you make a function accept multiple types?
how to pass different types to a function

 

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment

X