Functions
Basic Syntax
- lower case or uppercase name of function results in it being either public or internal to the package
package main
import (
"fmt"
)
// basic function scaffold
func main() {
}
Parameters
- can be values, in which case Go will make a copy and pass to the function scope
- can also be pointers, in which case if the function make any changes the parameters, the changes persist outside of the functions scope
- maps and slices have internal pointers referencing their underlying data, so function will always behave as if a pointers are being passed
// arguments to function
func sayMessage(msg string, i int) {
fmt.Println(msg)
fmt.Println(i)
}
// arguments to function
func sayMessage(msg string, name string) {
fmt.Println(msg, name)
}
// go will infer type to be the same for msg and name
func sayMessage(msg , name string) {
fmt.Println(msg, name)
}
package main
import (
"fmt"
)
func main() {
msg := "Hello "
name := "Yemane"
sayMessage(&msg, &name)
fmt.Println(msg, name)
}
// function takes pointers as arguments
func sayMessage(msg, name *string) {
fmt.Println(*msg, *name)
*msg = "Goodbye "
*name = "Yemane!"
}
package main
import (
"fmt"
)
func main() {
sum(1, 2, 3, 4, 5)
}
// variadic parameters
// values because a slice of all int passed
func sum(values ...int) {
fmt.Println(values)
result := 0
for _, v := range values {
result += v
}
fmt.Println(result)
}
Return Values
package main
import (
"fmt"
)
func main() {
s := sum(1, 2, 3, 4, 5)
fmt.Println(s)
}
// must indicate return type in function signature
func sum(values ...int) int {
fmt.Println(values)
result := 0
for _, v := range values {
result += v
}
return result
}
package main
import (
"fmt"
)
func main() {
s := sum(1, 2, 3, 4, 5)
fmt.Println(s)
}
// named return variable
func sum(values ...int) (result int) {
fmt.Println(values)
for _, v := range values {
result += v
}
return
}
package main
import (
"fmt"
)
func main() {
s := sum(1, 2, 3, 4, 5)
fmt.Println(*s)
}
// must indicate return type in function signature
func sum(values ...int) *int {
fmt.Println(values)
result := 0
for _, v := range values {
result += v
}
return &result
}
package main
import (
"fmt"
)
func main() {
d, err := divide(5.0, 0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(d)
}
// multiple return value, err handling
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0.0, fmt.Errorf("Cannot divide by zero")
}
return a / b, nil
}
Anonymous Functions
package main
import (
"fmt"
)
func main() {
// immediately invoked anonymous function
func(name string) {
fmt.Println("Hello ", name)
}("Yemane")
// anonymous function as a variable
f := func(name string) {
fmt.Println("Hello ", name, " Again")
}
f("Yemane")
}
Functions as types
package main
import (
"fmt"
)
func main() {
// declaring function type
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(5.0, 0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(d)
}
Methods
package main
import (
"fmt"
)
func main() {
//
g := greeter{
greeting: "hello",
name: "Go",
}
// use method
g.greet()
}
// greeter struct
type greeter struct {
greeting string
name string
}
// method is a function that executes in a known context (type)
func (g *greeter) greet() {
fmt.Println(g.greeting, g.name)
}