Skip to content

Latest commit

 

History

History
385 lines (279 loc) · 6.34 KB

README.md

File metadata and controls

385 lines (279 loc) · 6.34 KB

Functions

Functions

A function can take zero or more arguments.

package main

import "fmt"

func functionWithNoParameters() {
  fmt.Println("Function with no parameters called")
}

func functionWithNoParametersAndMultipleResult() (int, string) {
  return 30, "James Bond"
}

func functionWithParameters(s string) {
  fmt.Println(s)
}

func functionWithParametersAndSingleResult(s string) string {
  return s
}

func main() {
  functionWithNoParameters()

  age, name := functionWithNoParametersAndMultipleResult()
  fmt.Printf("Function with no parameters and multiple result called: %v %v\n", age, name)

  functionWithParameters("Function with parameters called")

  res := functionWithParametersAndSingleResult("Function with parameters and single result called")
  fmt.Println(res)
}

Output:

Function with no parameters called
Function with no parameters and multiple result called: 30 James Bond
Function with parameters called
Function with parameters and single result called

A function can return another function.

package main

import "fmt"

func main() {
  f := echo()
  fmt.Printf("%T\n", f)
  fmt.Println(f("James bond")) // function invocation
}

// echo returns an anonymous function
func echo() func(string) string {
  return func(x string) string {
    return x
  }
}

Output:

func(string) string
James bond

You can also pass function as arguments to another function and invoke it.

package main

import "fmt"

func sum(x ...int) int {
  total := 0
  for _, v := range x {
    total += v
  }
  return total
}

func evenSum(f func(num ...int) int, x ...int) int {
  var y []int
  for _, v := range x {
    if v%2 == 0 {
      y = append(y, v)
    }
  }
  return f(y...)
}

func main() {
  num := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

  sumOfAllNumbers := sum(num...)
  fmt.Printf("Sum of all numbers: %v\n", sumOfAllNumbers)

  sumOfEvenNumbers := evenSum(sum, num...)
  fmt.Printf("Sum of even numbers: %v", sumOfEvenNumbers)
}

Output:

Sum of all numbers: 45
Sum of even numbers: 20

Variadic Parameter

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.

The value passed is a new slice of type []T with a new underlying array.

package main

import "fmt"

func functionWithVariadicParameters(x ...int) {
  fmt.Println("Function with variadic parameters called")
  fmt.Println(x) // [1 2 3]
}

func main() {
  functionWithVariadicParameters(1, 2, 3)
}

If the final argument is a slice, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

package main

import "fmt"

func functionWithVariadicParameters(x ...int) {
  fmt.Println("Function with variadic parameters called")
  fmt.Println(x) // [1 2 3]
}

func main() {
  x := []int{1, 2, 3}
  functionWithVariadicParameters(x...)
}

Defer Statements

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

package main

import "fmt"

func f1() {
  fmt.Println("f1")
}

func f2() {
  fmt.Println("f2")
}

func main() {
  defer f1()
  f2()
}

Output:

f2
f1

Deferred function's arguments are evaluated when the defer statement is evaluated.

package main

import "fmt"

func f1(i int) {
  fmt.Println("f1: ", i)
}

func f2() {
  fmt.Println("f2")
}

func main() {
  i := 1
  defer f1(i) // 'i' is evaluated when f1 is deferred
  i++
  f2()
}

Output:

f2
f1:  1

Deferred function calls are executed in Last In First Out Order.

package main

import "fmt"

func f(i int) {
  fmt.Println(i)
}

func main() {
  for i := 0; i < 3; i++ {
    defer f(i)
  }

}

Output:

2
1
0

Method Declarations

A method is a function with a receiver. A method declaration binds an identifier, the method name, to a method, and associates the method with the receiver's base type.

The receiver is specified via an extra parameter section preceding the method name.

package main

import "fmt"

type person struct {
  firstName string
  lastName  string
}

/*
  Function with a receiver of type person
*/
func (p person) name() string {
  return p.firstName + " " + p.lastName
}

func main() {
  p := person{
    firstName: "James",
    lastName:  "Bond",
  }

  // method 'name' is bound to the receiver of type 'person' and is visible only within selectors for type 'person'
  fmt.Println(p.name())
}

Anonymous Functions

A function literal represents an anonymous function.

package main

import "fmt"

func main() {
  // Anonymous function with arguments
  func(x string) {
    fmt.Println(x)
  }("Anonymous Function")
}

A function literal can be assigned to a variable or invoked directly.

package main

import "fmt"

func main() {
  f := func(x string) {
    fmt.Println(x)
  }
  f("Anonymous Function")
}

Closures

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.

package main

import "fmt"

func incrementor() func() int {
  var x int
  return func() int {
    x++
    return x
  }
}

func main() {
  a := incrementor() // closure returned with x as 0
  b := incrementor() // closure returned with x as 0
  fmt.Println(a())   // increments x shared with closure assigned to 'a'
  fmt.Println(a())
  fmt.Println(a())
  fmt.Println(b()) // increments x shared with closure assigned to 'b'
  fmt.Println(b())
  fmt.Println(b())
}

Output:

1
2
3
1
2
3

Recursion

Call a function from within its own code.

package main

import "fmt"

func factorial(n int) int {
  if n == 1 {
    return 1
  }
  return n * factorial(n-1)
}

func main() {
  f := factorial(5)
  fmt.Println(f) // 120
}