How to pass parameters to go functions?
Before we understand golang optional parameter and mandatory parameter, we need to understand the basics of how a functions works in GO.
A parameter in Go and many other programming languages is information that is passed to a function. They act as variables inside a function. In Go however, parameters and their types need to be specified after the parameter name inside parenthesis of a function. By default, a function that has been defined to expect parameters, will force you to pass parameters.
Example
package main
import "fmt"
func PrintName(firstname, lastname string) {
fullName := fmt.Sprintf("%s %s", firstname, lastname)
fmt.Println(fullName)
}
func main() {
firstName := "John"
lastName := "Doe"
PrintName(firstName, lastName)
}
Explanation
The above example demonstrates a function that takes two parameters namely firstname
and lastname
. This function has one responsible of printing the full name. This function will throw an error if it is not passed the two parameters of type string. Optional parameters will allow us to call a function without passing parameters even when it expects one.We can also pass unlimited number of parameters to a function with optional parameters.
Output
$ go run main.go
John Doe
It would be nice to have a function that does not force us to pass parameters. In this article, our main focus will be Go optional parameters.Go by design does not support optional parameters. Go functions do not accept default parameter values and method overloading. Despite not having optional parameters natively, we can still achieve optional parameters . This article will explore optional parameters in Go using variadic functions. To learn more about functions in Go , check out the Go Function article.
Different methods to pass optional parameters to go functions
Method-1: Variadic function
Variadic function is a function that accepts a variable number of parameters. It is therefore possible to pass zero or varying number of arguments. To declare a variadic function, the type of the final parameter is preceded by an ellipsis “ … ”
. The ellipsis indicates that the function can be called with any number of parameters of a given type. This is useful because the number of parameters is not predetermined and therefore achieving optional parameters. Go Println()
function from the fmt
package is an example of a variadic function.
Example
package main
import "fmt"
// Accept any number of input arguments
func myVariadicFunc(params ...interface{}) {
fmt.Println("Executing ...")
for _, param := range params {
fmt.Println(param)
}
}
func main() {
firstName := "John"
lastName := "Doe"
age := 34
height := 5.5
myVariadicFunc(firstName, lastName, age, height)
myVariadicFunc(firstName, lastName)
myVariadicFunc()
}
Explanation
In the preceding example we define a variadic function that takes any type of parameters using the interface{}
type. We then iterate over these parameters and print them to the console.
We then call the myVariadicFunction()
three times with a varied number of parameters of type string, integer and float. It is worth noting that we have no errors despite passing zero number of parameters in the last function call.
Output
$ go run main.go
Executing ...
John
Doe
34
5.5
Executing ...
John
Doe
Executing ...
Method-2: Optional string parameters
We can pass optional string parameters to a variadic function. In the function signature, the eclipse is preceded with a string type.
Example
package main
import "fmt"
// Accept any number of input arguments
func printName(names ...string) {
fmt.Println("Start executing")
if len(names) == 0 {
fmt.Println("Zero number of parameters passed")
return
} else {
for i, name := range names {
fmt.Printf("%d ==> %s \n", i, name)
}
}
}
func main() {
printName("John Doe", "Sarah Doe", "George Williams")
printName()
}
Explanation
In the preceding example, we have defined a variadic function that takes string optional parameters. The names
variable stores all the string passed into the function as a slice. In the function body, we check the length of the names variable and iterate over the parameters if the length is more than one else we print a statement indicating that there are no parameters passed.
Output
$ go run main.go
Start executing
0 ==> John Doe
1 ==> Sarah Doe
2 ==> George Williams
Start executing
Zero number of parameters passed
Method-3: Optional numerical parameters
We can pass optional numeric parameters to a variadic function. In the method signature, the ellipsis will be preceded with integer
or float
types.
Example
package main
import "fmt"
func printHeight(heights ...float64) {
fmt.Println("Start executing")
for i, height := range heights {
fmt.Printf("%d ==> %f \n", i, height)
}
}
func main() {
printHeight(4.5, 6.0, 5.0, 3.0)
}
Output
$ go run main.go
Start executing
0 ==> 4.500000
1 ==> 6.000000
2 ==> 5.000000
3 ==> 3.000000
Method-4: Optional struct parameters
Optional parameters can also be of custom struct types. In the next example we will define a struct type.
Example
package main
import "fmt"
type human struct {
name string
}
func printPeople(people ...human) {
fmt.Println("Start executing")
for _, person := range people {
fmt.Printf("%s\n", person.name)
}
}
func main() {
person1 := human{name: "Elon Musk"}
person2 := human{name: "Bill Gates"}
person3 := human{name: "Warren Buffet"}
printPeople(person1, person2, person3)
}
Output
$ go run main.go
Start executing
Elon Musk
Bill Gates
Warren Buffet
Method-5: Optional function parameters
Functions in Go can also be treated as first-class citizens. First-class citizen means that a function can be treated as any other object and can be passed around like other values. Therefore a function can be passed as a parameter to another function. In this section ,we will combine the behavior of a variadic function and the first-class function , where we will pass an unlimited number of functions as parameters.
Example
package main
import "fmt"
type myMultiplier func(a float64) float64
func getSum(multipliers ...myMultiplier) float64 {
sum := 0.0
value := 2.0
for _, multiplier := range multipliers {
sum += multiplier(value)
}
return sum
}
func square(a float64) float64 {
return a * a
}
func cube(a float64) float64 {
return a * a * a
}
func main() {
sum := getSum(cube, cube, cube, cube, square, square, square)
fmt.Printf("Total sum is %f \n", sum)
}
Explanation
In the above example, we define a type called myMultiplier
of type function
that takes a number of type float64
and returns a number of type float64
. We also define a variadic function called getSum()
that takes in an array of functions that are of type myMultiplier
. The getSum()
returns the sum of all the calculations as a float64
. In this function , we iterate over the functions and calculate the sum
and return the final result as a float64. We also define two more functions called square()
and cube()
, of type myMultiplier
.
In the main function, we call the getSum()
function passing it cube()
and square()
functions. The getSum()
function can be passed unlimited number of functions that have the same signature as the myMultiplier()
Output
$ go run main.go
Total sum is 44.000000
Summary
Go by design does not support optional parameters and default parameters values passed to a function. Therefore not having optional parameters natively requires other methods to be used to make use of optional parameters. Go provides variadic functions that handle optional parameters.
References
https://bojanz.github.io/optional-parameters-go
https://yourbasic.org/golang/overload-overwrite-optional-parameter