A function is a named or anonymous block of code with a signature. A method is a function with a receiver. Generic functions and methods are covered on the Generics page.
Function declarations
FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
FunctionName = identifier .
FunctionBody = Block .
func add(a, b int) int {
return a + b
}
func div(a, b int) (q, r int, err error) {
if b == 0 {
err = errors.New("division by zero")
return
}
return a / b, a % b, nil
}
- A function with result parameters must end in a terminating statement.
- Named results act as local variables, set to zero values on entry. An empty
returnreturns their current values. - Arguments are passed by value: each is assigned to a new parameter variable.
- A function declaration without type parameters may omit the body, giving the signature of a function implemented outside Go, such as in assembly.
- Go has no default arguments and no function overloading. Function names must be unique
in a package, apart from
initand the blank identifier.
The conventional way to report failure is a final result of type
error, the predeclared interface with one method, Error() string;
nil means no error (spec: Errors).
Variadic functions
A final parameter of type ...T accepts zero or more arguments. Inside the
function it has type []T (spec: Passing arguments to ... parameters).
- With no arguments for it, its value is
nil. - Otherwise it is a new slice with a new underlying array holding the arguments, each of
which must be assignable to
T. - If the final argument is assignable to
[]Tand is followed by..., it is passed unchanged. No new slice is made, and the function sees the caller’s array.
func Greeting(prefix string, who ...string) { /* … */ }
Greeting("nobody") // who == nil
Greeting("hello:", "Joe", "Anna", "Eileen") // who == []string{"Joe", "Anna", "Eileen"}
s := []string{"James", "Jasmine"}
Greeting("goodbye:", s...) // who shares s's array
Function literals and closures
FunctionLit = "func" Signature FunctionBody .
A function literal is an anonymous function. It can be stored in a variable, passed as an argument or called on the spot. It is a closure: it refers to variables of the enclosing function, sharing them, and those variables live as long as they can be reached (spec: Function literals).
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
next := counter()
next() // 1
next() // 2
n alive after counter returnsSince Go 1.22, loop variables are per-iteration, so a closure created in a loop captures that iteration’s variable (see For statements).
Defer
DeferStmt = "defer" Expression .
A defer statement delays a function or method call until the surrounding
function returns, whether by a return, by reaching the end of its body, or by
panicking (spec: Defer statements).
- The expression must be a call, not parenthesised. The same built-in functions are restricted as for expression statements.
- Each time the statement executes, the function value and the arguments are evaluated and saved. The call itself happens later.
- Deferred calls run in reverse order: last deferred, first run.
- They run after
returnhas set any result parameters and before the function returns to its caller, so a deferred closure may change named results. - If the deferred function value is nil, the panic occurs when it is invoked, not when
deferexecutes. Any return values of the deferred call are discarded.
lock(l)
defer unlock(l) // unlocking happens before surrounding function returns
// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
defer fmt.Print(i)
}
// f returns 42
func f() (result int) {
defer func() {
// result is accessed after it was set to 6 by the return statement
result *= 7
}()
return 6
}
Panic and recover
A panic is an explicit call of the built-in panic or a run-time error,
such as an index out of range (spec: Run-time panics). It stops the current function, runs
deferred calls up the stack of that goroutine, and if nothing recovers terminates the
program. The error reports the value passed to panic.
func panic(interface{})
func recover() interface{}
recover regains control of a panicking goroutine. If a function
G defers a function D that calls recover, and a panic
occurs in a function on the same goroutine in which G is executing, then when
the deferred functions reach D, recover returns the value given to
panic. If D returns normally without panicking again, the sequence
stops and G returns to its caller after its other deferred functions run.
recoverreturns nil if the goroutine is not panicking or it was not called directly by a deferred function. If it was, the result is guaranteed not to be nil (Go 1.21).- To ensure that, calling
panicwith a nil interface value or an untyped nil causes a run-time panic of type*runtime.PanicNilError(Go 1.21). - Run-time panics have the interface type
runtime.Error, which satisfieserror.
func protect(g func()) {
defer func() {
log.Println("done") // Println executes normally even if there is a panic
if x := recover(); x != nil {
log.Printf("run time panic: %v", x)
}
}()
log.Println("start")
g()
}
gMethod declarations
MethodDecl = "func" Receiver MethodName [ TypeParameters ] Signature [ FunctionBody ] .
Receiver = Parameters .
A method is a function with a receiver, an extra parameter section before the
method name that must declare one non-variadic parameter (spec: Method declarations). Its
type must be a defined type T or a pointer to one, called the base
type. The base type cannot be a pointer or interface and must be defined in the same
package as the method.
type Point struct{ x, y float64 }
func (p Point) Length() float64 { // value receiver
return math.Sqrt(p.x*p.x + p.y*p.y)
}
func (p *Point) Scale(factor float64) { // pointer receiver
p.x *= factor
p.y *= factor
}
- A value receiver works on a copy. A pointer receiver can change the original value.
- The method name is visible only through selectors on
Tor*T. Non-blank method names must be unique on a base type, and on a struct must differ from its field names. - If the receiver is not used in the body, its identifier may be omitted.
- Calling
x.m()with a pointer receiver on an addressable value is shorthand for(&x).m(). See Calls. - Which methods a type has is described by its method set.
- A method of a generic base type declares matching type parameters in its receiver. A method may also declare type parameters of its own (Go 1.27); see Generics.
Method values and method expressions
There is no distinct method type and there are no method literals. Methods turn into function values in two ways.
| Form | Example | Result |
|---|---|---|
| Method value (Go 1.1) | x.M | A function with the receiver bound; the expression x is evaluated and copied when the value is made |
| Method expression | T.M, (*T).M | A function whose first argument is the receiver |
type T struct{ a int }
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
var pt *T
f := t.Mv // method value: func(int) int, receiver copied now
f(7) // like t.Mv(7)
g := T.Mv // method expression: func(tv T, a int) int
g(t, 7)
h := (*T).Mv // func(tv *T, a int) int; indirects through the pointer
m := (*T).Mp // func(tp *T, f float32) float32
// T.Mp is illegal: Mp is not in the method set of T
- A method value of a value receiver saves a copy of the receiver at that moment; a later change to the original does not affect it.
- As with calls, a pointer dereferences automatically for a value receiver
(
pt.Mv) and an addressable value has its address taken for a pointer receiver (t.Mp).makeT().Mpis invalid because a function result is not addressable. - A method value of an interface type is legal, and so is a method expression on an interface type, which takes a receiver of that interface type.