Functions
Function arguments of same type can be separated by comma and declare type only in the end
// Both greeting and name variables are same string type, so no need to define type for each of them
func sayGreeting(greeting, name string) {
fmt.Println(greeting, name)
}
Example of function with pointer arguments. Note, slice and maps always passed by reference even if there is no pointer operators.
// Output:
// Hello John
// James
// James
func main() {
greeting := "Hello"
name := "John"
sayGreeting(&greeting, &name)
fmt.Println(name)
s := []int{1,2,3}
changeSlice(s)
// output: [0,2,3]
fmt.Println(s)
}
func sayGreeting(greeting, name *string) {
fmt.Println(*greeting, *name)
*name = "James"
fmt.Println(*name)
}
func changeSlice(slice []int) {
slice[0] = 0
}
Functions can accept variadic parameters. They must be placed as last and only once. Parameters will be converted to slice.
func main() {
sum("The sum is:", 1, 2, 3, 4)
}
// values is variadic parameter and it is slice of integers
func sum(msg string, values ...int) {
result := 0
for _, v := range values {
result += v
}
// Output: The sum is: 10
fmt.Println(msg, result)
}
Function can return pointer instead of value
func main() {
s := sum(1, 2, 3, 4)
fmt.Println("The sum is:", *s)
}
func sum(values ...int) *int {
result := 0
for _, v := range values {
result += v
}
return &result
}
Function can define mean return value:
func main() {
s := sum(1, 2, 3, 4)
fmt.Println("The sum is:", s)
}
func sum(values ...int) (result int) {
for _, v := range values {
result += v
}
// this is syntax sugar so interpreter will just return result variable
return
}
Function can return multiple values:
func main() {
d, err := divide(5.0, 0.0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(d)
}
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0.0, fmt.Errorf("Cannot divide by zero")
}
return a / b, nil
}
Function is type so it can be declared as variables, can be passed as parameters and can be return result of another function
func main() {
// Here we define variable as simple anonymous function without parameters and return values
var simplePrint func()
simplePrint = func() {
fmt.Println("Hello world")
}
// Output: Hello world
simplePrint()
// Here we define variable that has type of function with 2 float64 parameter and float64, error return values
var divide func(float64, float64) (float64, error)
divide = func(a, b float64) (float64, error) {
if b == 0 {
return 0.0, fmt.Errorf("Cannot divide by zero")
}
return a / b, nil
}
d, err := divide(1.0, 0.0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(d)
}
Types can contain methods. Then receiver will be defined in parentheses before function name
func main() {
g := greeter{
greeting: "Hello",
name: "John",
}
g.greet()
var c counter
c = 0
c.increment()
// output: 1
fmt.Println(c)
}
type greeter struct {
greeting string
name string
}
// By default receiver for the method(g greeter in this case) is passing by value. To pass by reference need to use pointer operator
func (g greeter) greet() {
fmt.Println(g.greeting, g.name)
}
type counter int
func (c *counter) increment() {
*c++
}