Function declarations

August 21, 2023

No livestream today. My family is on vacation this week. I’ll be livestreaming again next week!


Function declarations

A function declaration binds an identifier, the function name, to a function.

FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
FunctionName = identifier .
FunctionBody = Block .

Nothing surprising here… So let’s move on to the first interesting rule:

If the function’s signature declares result parameters, the function body’s statement list must end in a terminating statement.

func IndexRune(s string, r rune) int {
	for i, c := range s {
		if c == r {
			return i
		}
	}
	// invalid: missing return statement
}

This also makes pretty intuitive sense, but it’s not enforced in all languages, so it’s worth pointing out. Particularly many dynamic languages don’t require an explicit return, and fall back to some sort of default return value when it is omitted. Not true in Go. You must have an explicit return value if the function signature indicates that the function returns something.

But let’s look at one potentially surprising case. The following code is valid, even though the last line is not a return statement. See if you can’t figure out why. (If you can’t, hit reply and let me know… I may do a follow-up post).

func whatType(i any) string {
	switch t := i.(type) {
	case string:
		return "string"
	case int, int8, int16, int32, int64, uint, uint8, uint8, uint16, uint32, uint64:
		return "integer"
	case float32, float64:
		return "floating point"
	default:
		return "unknown"
	}
  // No return statement... yet this is valid!
}

Quotes from The Go Programming Language Specification Version of August 2, 2023

Share this

Related Content

Empty function declarations

Function declarations … A function declaration without type parameters may omit the body. Such a declaration provides the signature for a function implemented outside Go, such as an assembly routine. func flushICache(begin, end uintptr) // implemented externally This is something I have never used. Most developers probably never will. Although I’ve certainly seen it a few times, particularly while browsing the standard library source code, so it’s good to be aware of it, so you aren’t stuck scratching your head when you see it.

Generic function declarations

Function declarations … If the function declaration specifies type parameters, the function name denotes a generic function. A generic function must be instantiated before it can be called or used as a value. func min[T ~int|~float64](x, y T) T { if x < y { return x } return y } We’ve mentioned instantiation before, but it will be covered in depth later. For now, it’s enough to show an example of what the spec means can’t be done without instantiating a generic function:

Where declarations are allowed

First, a big thanks to everyone who showed up for yesterday’s first Boldly Go Live stream. We had some audio problems, which I promise to fix before the next one. But otherwise it was a success, with some great discussion. You can catch the replay if you missed it. Here we are at the formal description of declaration syntax. Declarations and scope … Declaration = ConstDecl | TypeDecl | VarDecl .