Functions and Methods
Table of Contents
- Basics of
func
- Does Go support function overloading?(functions with the same name)
- Defining Anonymous functions within a loop
Basics of func
tutorial
- If the name begins with an upper-case letter, it is exported(accessible outside of its own package)
- No default parameter values
- No keyword(or named) arguments
- Arguments are passed by value.
- The zero value of a function type is
nil
.
func add(x int, y int) int {
return x + y
}
// Declarations of consecutive same type parameters can be coalesced.
func add(x, y int) int {
return x + y
}
// Return values can be named, in which case
// the name declares a local variable initialized to the zero value for its type.
func add(x, y int) (z int) {
z = x + y
return // this is called 'naked(or bare) return'
}
// Functions can have multiple return values
func addsub(x, y int) (int, int) {
return x + y, x - y
}
Deferred functions
4 3 2 1 0
- Schedules a function call (the deferred function) to be run immediately before the function which executes the defer returns.
- Deferred functions are executed in LIFO order.
- The arguments to the deferred function are evaluated when the defer executes(or registering phase), not when the call executes.
Variadic functions; within the body of the function, the type of
vals
is an []int
slice.
Place
...
after the final argument to call a function with elements of a slice.
(p Point)
is called the method's receiver.- Though methods are placed under its receiver type,
T
and*T
are considered the same receiver type. - It should be avoided to use the receiver type
T
for some methods and*T
for others. AllT
orAll ~*T
. - Generally, receivers will be referred frequently, giving a short name is recommended, like the first letter of the type name.
- Each type has its own name space for methods, so it is possible to use the same method name for different types.
- Unlike other languages, in Go, it is allowed to define methods for any types, even primitive types.
It is possible to call methods of embedded types
type Point struct{ X, Y float64 }
type Circle struct {
Point
Radius float64
}
func (p Point) Distance(q Point) float64 {}
p := Point{0, 0}
c := Cricle{Point{1, 2}, 3}
c.Distance(p)
// error! only receivers can be promoted
p.Distnace(c)
// To fix it, select the anonymous field explicitly
p.Distnace(c.Point)
When the compiler encounters c.Distance(p)
- First try to find
func (Cricle) Distance(Point)
- If it does not exist, it looks for the method within the embedded fields
- If it finds one, it will generate additional wrapper so that it could be called seamlessly.
Method Values and Expressions
package main
type Point struct{ X, Y float64 }
func (p Point) Distance(q Point) float64 {
return 0.0
}
p := Point{1, 2}
q := Point{3, 4}
// Method value, bound to `p`
distanceFromP := p.Distance
distanceFromP(q)
// Method expression. The receiver should be passed as the first parameter.
distance := Point.Distance
distance(p, q)
Does Go support function overloading?(functions with the same name) discussion
- No, you cannot define same name methods for different argument types.
- Instead, use the same named methods of different receivers, which is supported.
Defining Anonymous functions within a loop discussion
Be careful when defining anonymous functions, which use the iterator variable, within a loop. Consider a situation in which you need to define functions which reference elements of a slice.
names := []string{"cwkim", "sublee", "suminb", "yeonghoey"}
funcs := []func(){}
for _, name := range names {
funcs = append(funcs, func() {
fmt.Println(name) // wrong! `name` changes over the for loop
})
}
for _, f := range funcs {
f()
}
yeonghoey
yeonghoey
yeonghoey
yeonghoey
To fix this, we need to define a new scope variable and make the function reference it.
names := []string{"cwkim", "sublee", "suminb", "yeonghoey"}
funcs := []func(){}
for _, name := range names {
name := name // necessary!
funcs = append(funcs, func() {
fmt.Println(name)
})
}
for _, f := range funcs {
f()
}
sublee
cwkim
suminb
yeonghoey