There are some cases where we can’t specify the number of parameters for a function. How can we define such a function in Golang?
Variadic function declaration
It’s easy to do it in Go. Prepend three dots before the data type.
func arbitraryNumbers(args ...int) {
fmt.Println("--- arbitraryNumbers ---")
fmt.Printf("0: %d, 1: %d\n", args[0], args[1])
for index, arg := range args {
fmt.Printf("%d: %d, ", index, arg)
}
fmt.Println()
}
func arbitraryStrings(args ...string) {
fmt.Println("--- arbitraryStrings ---")
fmt.Printf("0: %s, 1: %s\n", args[0], args[1])
for index, arg := range args {
fmt.Printf("%d: %s, ", index, arg)
}
fmt.Println()
}
The parameters are handled as an array so that we can read the value with an index.
The function can be called in the following way.
arbitraryNumbers(22, 77, 44, 57, 92, 23)
// --- arbitraryNumbers ---
// 0: 22, 1: 77
// 0: 22, 1: 77, 2: 44, 3: 57, 4: 92, 5: 23,
arr := []int{22, 77, 44, 57, 92, 23}
arbitraryNumbers(arr...)
// --- arbitraryNumbers ---
// 0: 22, 1: 77
// 0: 22, 1: 77, 2: 44, 3: 57, 4: 92, 5: 23,
arbitraryStrings("Hello", "Wor", "ld", "!!!")
// --- arbitraryStrings ---
// 0: Hello, 1: Wor
// 0: Hello, 1: Wor, 2: ld, 3: !!!,
We can add as many parameters as we want. If the target variable we want to pass is an array/slice, add the three dots after the variable. It expands the array. So the result is the same.
How to pass multipe data types to a function
If we want to pass both int and string to the function, we can use any
. It is an alias as interface{}
. It can be used from 1.18.
func arbitraryAny(args ...any) {
fmt.Println("--- arbitraryAny ---")
fmt.Printf("0: %v, 1: %v\n", args[0], args[1])
for index, arg := range args {
fmt.Printf("%d: %v, ", index, arg)
}
fmt.Println()
}
arbitraryAny("Hello", 123, "Wor", 987, "ld", 888, "!!!")
// --- arbitraryAny ---
// 0: Hello, 1: 123
// 0: Hello, 1: 123, 2: Wor, 3: 987, 4: ld, builtin5: 888, 6: !!!,
Variadic function accepts struct type as well
It might accept a struct type. We can handle it in the same way as built-in types.
func arbitraryArgs(args ...any) {
fmt.Println("--- arbitraryArgs ---")
for index, val := range args {
fmt.Printf("%d: ", index)
switch v := val.(type) {
case string:
fmt.Println("String ", v)
case int:
fmt.Println("Int ", v)
case float64:
fmt.Println("Float64 ", v)
case unknownObj1:
fmt.Println("Special ", v)
default:
fmt.Println("Unknown data type: ", reflect.TypeOf(v))
}
}
}
arbitraryArgs(12, "string-value", []int{1, 2, 3}, 55, obj1, obj2)
// --- arbitraryArgs ---
// 0: Int 12
// 1: String string-value
// 2: Unknown data type: []int
// 3: Int 55
// 4: Special {Yuto Hello World!}
// 5: Unknown data type: utils.unknownObj2
If the value is a struct, we can access the property.
Check the following post too if you need to know any
and interface{}
.
Comments