Sunday 4 April 2021

Special handling of functions in Go

This is a study note for YouTube tutorial: https://www.youtube.com/watch?v=YS4e4q9oBaU&t=12079s

This post only talks about some special parts of Go functions.

Function name

Like variables, functions starting with lower case will keep private to the package, however functions starting with upper case will be exposed to the outside of the package.

Function parameters

1, if the function has parameters with same type, you can simply put the type at the last parameter in the function. For example.
func main() {
greet("Hello", "Tiffany")
}

func greet(greeting, name string) {
println(greeting, name)
}

The output is:
Hello Tiffany

2, you can use variadic parameters in Go.

func main() {
sum(1, 2, 3, 4, 5)
}

func sum(values ...int) {
sum := 0
for _, v := range values {
sum += v
}
fmt.Println("The sum is ", sum)
}

The output is:
The sum is 15

You can use variadic parameter with other parameter, but the function can only have one variadic parameter and it must be at the end.

Function return

1, When define function, put the return type after the closing bracket ")".

func main() {
fmt.Println("The result is: ", sum(1, 2, 3, 4, 5))
}

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

2, You can return a pointer from a function as well. Unlike in C/C++, when you turn a pointer in call stack, you can get as undefined behaviour because the stack will be destroyed when the function returns. Thus, you cannot control what is in the pointer now. However in Go, when Go detect you are returning a pointer from stack, it will automatically promote this variable from stack to heap, so you don't need to be worry about the value in the pointer is destroyed.

func main() {
fmt.Println("The result is: ", *sum(1, 2, 3, 4, 5))
}

func sum(values ...int) *int {
sum := 0
for _, v := range values {
sum += v
}
return &sum
}

3, You can use multiple returns in Go functions. The most useful cases of multiple returns is to add an error message in a function to indicate if the function execution is successful.

func main() {
result, err := divide(5.0, 0.0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
}

func divide(a, b float64) (float64, error) {
if b == 0.0 {
return 0.0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}

Function as a variable

You can use function as a value to assign a variable.
func main() {
f := func() {
fmt.Println("Hello world")
}
f()
}

You can specify the signature of the function like below.

func main() {

var divide func(float64, float64) (float64, error)
divide = func(f1, f2 float64) (float64, error) {
if f2 == 0.0 {
return 0.0, fmt.Errorf("cannot divide by zero")
}
return f1 / f2, nil
}
result, err := divide(5.0, 0.0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
}

Method

You can create a function executing in a known context (like struct, int... any type actually, but most of cases are used with structs).

func main() {
g := greeter{
greeting: "Hello",
name: "Tiffany",
}
g.greet()

}

type greeter struct {
greeting string
name string
}

func (g greeter) greet() { // (g greeter) make this function a method
fmt.Println(g.greeting, g.name)
}




Reference:  https://www.youtube.com/watch?v=YS4e4q9oBaU&t=12079s

No comments:

Post a Comment

Difference between "docker stop" and "docker kill"

 To stop a running container, you can use either "docker stop" or "docker kill" command to do so. Although it seems doin...