Function types

March 29, 2023

Go has first-class functions. That is to say, functions are treated as any other data type, and can be passed around as arguments, used as struct field types, etc.

Function types

A function type denotes the set of all functions with the same parameter and result types. The value of an uninitialized variable of function type is nil.

FunctionType   = "func" Signature .
Signature      = Parameters [ Result ] .
Result         = Parameters | Type .
Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

Notice the definition, though: A function type denotes the set of all functions with the same parameter type and result types. Nothing is said about the names of those parameters and results. This means that the following two functions are of the same type:

func(x int) int
func(y int) int

As are these:

func(r *http.Request) (err error)
func(req *httpRequest) error

The parameter and result names don’t affect the function’s type at all.

Quotes from The Go Programming Language Specification Version of December 15, 2022

Share this

Related Content

Variadic functions

Generally speaking, Go doesn’t allow for the use of optional function parameters. But there is one exception, and that’s where variadic functions come into play. Function types The final incoming parameter in a function signature may have a type prefixed with .... A function with such a parameter is called variadic and may be invoked with zero or more arguments for that parameter. Probably the most ubiquitous example of a variadic function would be fmt.

Unparenthesized results

Function types … Parameter and result lists are always parenthesized except that if there is exactly one unnamed result it may be written as an unparenthesized type. But more directly: Function parameters must always be wrapped in parenthesis. Function reults must be wrapped in parenthesis if there is more than one result, or if the result is named. Further, though not clear from this wording in the spec, if there are no results, no parenthesis are required, even though if there are no parameters, they are still required.

Collapsing like function parameters

Yesterday we learned that we may omit function parameter and result names in a function type definition. But this poses a small limitation: Function types … If [the name is] absent, each type stands for one item of that type. What does that mean, exactly? Well, when using named parameters and results, we have the option to omit the type for subesquent arguments of the same type. Here’s an example to make it more clear;