# Control statements and functions

## Control statements

### if

`if` doesn't need parentheses in Go.

```golang
if x > 10 {
	//when x is greater than 10
	//program enters this block
	fmt.Println("x is greater than 10")
} else {
	//when x is smaller than 10
	//program enters this block
	fmt.Println("x is less than or equal to 10")
}
```

Go allows us to initialize and use variables in if like this:

```golang
// initialize x, then check if x greater than
if x := computedValue(); x > 10 {
	fmt.Println("x is greater than 10")
} else {
	fmt.Println("x is less than 10")
}

// the following code will not compile
fmt.Println(x)
```

For multiple conditions we use the else if block

```golang
if integer == 3 {
	fmt.Println("The integer is equal to 3")
} else if integer < 3 {
	fmt.Println("The integer is less than 3")
} else {
	fmt.Println("The integer is greater than 3")
}
```

### goto

Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the control flow to a previously defined `label` within the body of same code block.

```golang
func myFunc() {
	i := 0
Here:   // label ends with ":"
	fmt.Println(i)
	i++
	goto Here   // jump to label "Here"
}
```

The label name is case sensitive.

### for

Go does not have while, do while. Just a `for`, which is the most powerful control logic. It can read data in loops and iterative operations, just like `while`. Like `if`, `for` doesn't need parenthesis.

```golang
for expression1; expression2; expression3 {
	//...
}
```

```golang
package main
import "fmt"

func main(){
	sum := 0;
	for index:=0; index < 10 ; index++ {
		sum += index
	}
	fmt.Println("sum is equal to ", sum)
}
// Print: sum is equal to 45
```

We can omit one or more expressions.

```golang
sum := 1
for ; sum < 1000;  {
	sum += sum
}

for {
	//this is an infinite loop
}
```

Using `for` like a `while`

```golang
sum := 1
for sum < 1000 {
	sum += sum
}
```

#### break and continue

`break`: jumps out of the loop. If you have nested loops, use `break` along with labels.

`continue` skips the current loop and starts the next one

```golang
for index := 10; index>0; index-- {
	if index == 5{
		break // or continue
	}
	fmt.Println(index)
}
// break prints 10、9、8、7、6
// continue prints 10、9、8、7、6、4、3、2、1
```

`for` can read data from `slice` and `map` when it is used together with `range`.

```golang
for k,v:=range map {
	fmt.Println("map's key:",k)
	fmt.Println("map's val:",v)
}
```

Because Go supports multi-value returns and gives compile errors when you don't use values that were defined, as discussed earlier, `_` is used to discard certain return values.

```golang
for _, v := range map{
	fmt.Println("map's val:", v)
}
```

#### switch

Switch is an easier way to avoid long `if-else` statements.

```golang
switch sExpr {
case expr1:
	some instructions
case expr2:
	some other instructions
case expr3:
	some other instructions
default:
	other code
}
```

The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same.

Conditions don't have to be constants and it checks the cases from top to bottom until it matches conditions and executes only the matching case.

If there is no statement after the keyword `switch`, then it matches `true`.

The default case is when there is no match to the switch.

```golang
i := 10
switch i {
case 1:
	fmt.Println("i is equal to 1")
case 2, 3, 4:
	fmt.Println("i is equal to 2, 3 or 4")
case 10:
	fmt.Println("i is equal to 10")
default:
	fmt.Println("All I know is that i is an integer")
}
```

Cases can have more than one values separated by a comma. By default switch executes only the matching case, however we can make switch execute the matching case and all cases below it using the `fallthrough` statement.

```golang
integer := 6
switch integer {
case 4:
	fmt.Println("integer <= 4")
	fallthrough
case 5:
	fmt.Println("integer <= 5")
	fallthrough
case 6:
	fmt.Println("integer <= 6")
	fallthrough
case 7:
	fmt.Println("integer <= 7")
	fallthrough
case 8:
	fmt.Println("integer <= 8")
	fallthrough
default:
	fmt.Println("default case")
}
```

This program prints the following information.

integer <= 6 integer <= 7 integer <= 8 default case

## Functions

`func` keyword is used to define a function.

```golang
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
	// function body
	// multi-value return
	return value1, value2
}
```

* Functions may have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`.
* Functions can return multiple values.
* There are two return values named `output1` and `output2`, you can omit their names and use their type only.
* If there is only one return value and you omitted the name, you don't need brackets for the return values.
* If the function doesn't have return values, you can omit the return parameters altogether.
* If the function has return values, you have to use the `return` statement somewhere in the body of the function.

A simple program to calculate maximum value.

```golang
package main
import "fmt"

// returns the greater value between a and b
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	x := 3
	y := 4
	z := 5

	max_xy := max(x, y) // call function max(x, y)
	max_xz := max(x, z) // call function max(x, z)

	fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
	fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
	fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // call function here
}
```

In a function call, if two or more arguments have the same data type, then we can put the data type only after the last argument.

`func max(a,b int, c,d string)`: this means we have four arguments, a,b: integers and c,d: string.

### Multi-value return

```golang
package main
import "fmt"

// return results of A + B and A * B
func SumAndProduct(A, B int) (int, int) {
	return A+B, A*B
}

func main() {
	x := 3
	y := 4

	xPLUSy, xTIMESy := SumAndProduct(x, y)

	fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
	fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}
```

SumAndProduct will return two values without names. Go allows us to have named return arguments. By using named arguments, the respective variables are returned automatically, we would just need to use `return`.

If functions are going to be used outside of current program, it is better to explicitly write return statements for the sake of readability.

```golang
func SumAndProduct(A, B int) (add int, multiplied int) {
	add = A+B
	multiplied = A*B
	return
}
// Since return arguments are named, the function automatically
// returns them
```

### Variadic arguments to functions

In many cases, we do not know how many arguements can be passed, in such cases, we use variadic arguments.

func myfunc(arg ...int) {}

`arg …int` tells Go that this is a function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`.

for \_, n := range arg { fmt.Printf("And the number is: %d\n", n) }

### Pass by value and pointers

Argument are passed by value to the functions, the argument change inside the function doesn't affect the arguments used to call the function.

```golang
package main
import "fmt"

// simple function to add 1 to a
func add1(a int) int {
	a = a+1 // we change value of a
	return a // return new value of a
}

func main() {
	x := 3

	fmt.Println("x = ", x)  // should print "x = 3"

	x1 := add1(x)  // call add1(x)

	fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
	fmt.Println("x = ", x)    // should print "x = 3"
}
```

The original value of `x` doesn't change, because we passed x as a value, so the function add1 created a copy of x. Despite having the same names, the both variables are totally independent of each other.

In cases where we want to be able to modify the argument's value, we use pass by reference using pointers.

In reality, a variable is nothing but a pointer to a location in memory. Each variable has a unique memory address. So, if we want to change the value of a variable, we must change its memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value.

```golang
package main
import "fmt"

// simple function to add 1 to a
func add1(a *int) int {
	*a = *a+1 // we changed value of a
	return *a // return new value of a
}

func main() {
	x := 3

	fmt.Println("x = ", x)  // should print "x = 3"

	x1 := add1(&x)  // call add1(&x) pass memory address of x

	fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
	fmt.Println("x = ", x)    // should print "x = 4"
}
```

Advantages of pointers:

* Allows us to use more functions to operate on one variable.
* Low cost by passing memory addresses (8 bytes), copy is not an efficient way, both in terms of time and space, to pass variables.
* `string`, `slice` and `map` are reference types, so they use pointers when passing to functions by default. (Attention: If you need to change the length of `slice`, you have to pass pointers explicitly)

### defer

Defer postpones the execution of a function till the calling function has finished executing. You can have many `defer` statements in one function; they will execute in reverse order when the program reaches its end. In the case where the program opens some resource files, these files would have to be closed before the function can return with errors. Let's see some examples.

```golang
func ReadWrite() bool {
	file.Open("file")
	// Do some work
	if failureX {
		file.Close()
		return false
	}

	if failureY {
		file.Close()
		return false
	}

	file.Close()
	return true
}
```

We saw some code being repeated several times. `defer` solves this problem very well. It doesn't only help you to write clean code but also makes your code more readable.

```golang
func ReadWrite() bool {
	file.Open("file")
	defer file.Close()
	if failureX {
		return false
	}
	if failureY {
		return false
	}
	return true
}
```

If there are more than one `defer`s, they will execute by reverse order. The following example will print `4 3 2 1 0`.

```golang
for i := 0; i < 5; i++ {
	defer fmt.Printf("%d ", i)
}
```

### Functions as values and types

Functions are also variables in Go, we can use `type` to define them. Functions that have the same signature can be seen as the same type.

type typeName func(input1 inputType1 , input2 inputType2 \[, ...]) (result1 resultType1 \[, ...])

This makes Go a functional language as functions are a first class citizen.

```golang
package main
import "fmt"

type testInt func(int) bool // define a function type of variable

func isOdd(integer int) bool {
	if integer%2 == 0 {
		return false
	}
	return true
}

func isEven(integer int) bool {
	if integer%2 == 0 {
		return true
	}
	return false
}

// pass the function `f` as an argument to another function

func filter(slice []int, f testInt) []int {
	var result []int
	for _, value := range slice {
		if f(value) {
			result = append(result, value)
		}
	}
	return result
}

func main(){
	slice := []int {1, 2, 3, 4, 5, 7}
	fmt.Println("slice = ", slice)
	odd := filter(slice, isOdd)    // use function as values
	fmt.Println("Odd elements of slice are: ", odd)
	even := filter(slice, isEven)
	fmt.Println("Even elements of slice are: ", even)
}
```

It's very useful when we use interfaces. As you can see `testInt` is a variable that has a function as type and the returned values and arguments of `filter` are the same as those of `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code.

### Panic and Recover

Go doesn't have `try-catch` structure like Java does. Instead of throwing exceptions, Go uses `panic` and `recover` to deal with errors. However, you shouldn't use `panic` very much, although it's powerful.

`Panic` is a built-in function to break the normal flow of programs and get into panic status. When a function `F` calls `panic`, `F` will not continue executing but its `defer` functions will continue to execute. Then `F` goes back to the break point which caused the panic status. The program will not terminate until all of these functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds errors.

`Recover` is a built-in function to recover `goroutine`s from panic status. Calling `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` values if the program is in the panic status, and it gets `nil` if the program is not in panic status.

The following example shows how to use `panic`.

```golang
var user = os.Getenv("USER")

func init() {
	if user == "" {
		panic("no value for $USER")
	}
}
```

The following example shows how to check `panic`.

```golang
func throwsPanic(f func()) (b bool) {
	defer func() {
		if x := recover(); x != nil {
			b = true
		}
	}()
	f() // if f causes panic, it will recover
	return
}
```

### main and init functions

Go has two retentions which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. These two functions are not able to have arguments or return values. Even though we can write many `init` functions in one package, I strongly recommend writing only one `init` function for each package.

Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, the `init` function is optional, but `package main` has one and only one `main` function.

Programs initialize and begin execution from the `main` package. If the `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After importing packages, programs will initialize the constants and variables within the imported packages, then execute the `init` function if it exists, and so on. After all the other packages are initialized, programs will initialize constants and variables in the `main` package, then execute the `init` function inside the package if it exists. The following figure shows the process.

![Flow of programs initialization](/files/-M7GbbhKMFBcylKXCcAO)

### import

`import` is very often used in Go programs.

```golang
import(
	"fmt"
)
```

Methods of `fmt` are called as follows.

```golang
fmt.Println("hello world")
```

`fmt` is from Go standard library, it is located within $GOROOT/pkg. Go supports third-party packages in two ways.

1. Relative path import "./model" // load package in the same directory, I don't recommend this way.
2. Absolute path import "shorturl/model" // load package in path "$GOPATH/pkg/shorturl/model"

There are some special operators when we import packages, and beginners are always confused by these operators.

**Dot operator**

Sometimes we see people use following way to import packages.

```golang
import(
	. "fmt"
)
```

The dot operator means you can omit the package name when you call functions inside of that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`.

**Alias operation**

It changes the name of the package that we imported when we call functions that belong to that package.

```golang
import(
	f "fmt"
)
```

Now `fmt.Printf("Hello world")` becomes to `f.Printf("Hello world")`.

**`_` operator**

This is the operator that is difficult to understand without someone explaining it to you.

```golang
import (
	"database/sql"
	_ "github.com/ziutek/mymysql/godrv"
)
```

The `_` operator actually means we just want to import that package and execute its `init` function, and we are not sure if want to use the functions belonging to that package.

### Links

-[Previous section](/bo/02.1introductiongo/02.2variablesdatastruct.md) -[Next section](/bo/02.1introductiongo/02.4struct.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thewhitetulip.gitbook.io/bo/02.1introductiongo/02.3cntrlstmtfunctions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
