Declaring Functions
From: functions.go
4 func printf(str string, args ...interface{}) (int , error) { 5 _, err := fmt.Printf(str, args...) 6 return len(args), err 7 } 8 9 func main() { 10 count := 1 11 closure := func(msg string) { 12 printf("%d %s\n", count, msg) 13 count++ 14 } 15 closure("A Message") 16 closure("Another Message") 17 }
Functions in Go are declared using the func keyword. As with variable declarations, the return type goes at the end. This can be a single value, or a list of values. The printf() function in the example shows several important features of Go. This is a variadic function, which returns multiple values: an integer and an error. The integer is the number of variadic arguments passed to it, and the error code is one of the values returned from the Printf() function from the fmt package.
Note the syntax for calling functions that return multiple values. The return values must either all be ignored, or all assigned to variables. The blank identifier, _, can be used for values that you wish to discard.
Variadic functions in Go are particularly interesting. In C, a variadic function call just pushes extra parameters onto the stack, and the callee has to know how to pop them off. In Go, all variadic parameters are delivered as a slice (see Chapter 5, Arrays and Slices; for now you can think of a slice as being like an array). The variadic parameters must all be of the same type, although you can use the empty interface type (interface{}) to allow variables of any type and then use type introspection to find out what they really are.
The main() function in the example is the program entry point. Unlike many other languages, this takes no arguments. Command-line arguments and environment variables are stored globally in Go, making it easy to access them from any function, not just one near the program entry point.
Inside this function, you’ll see a closure defined. Closures in Go are declared as anonymous functions, inside other functions. The closure can refer to any variables in the scope where it is declared. In this example, it refers to the count variable from the outer function’s scope. It would continue to do so even after the outer function returned. In Go, there is no distinction between heap and stack allocated variables, except at the implementation level. If a local variable is referenced after the function that contains it, then it is not freed when the function returns. If closure were stored in a global variable, for example, then count would not be deallocated, even after the function returned.