Processing flow (if, for, switch, defer, select)

We will check Go’s “basic control syntax (if, for, switch, for)” and “control syntax used in parallel processing (select)”.

TOC

if

package main

import (
	"fmt"
	"time"
)

func main() {
	i := 5
	if i > 0 {
		fmt.Println("xxx")
	}

	if t := time.Now(); t.Hour() < 14 {
		// Scope of variable t until end of if
		fmt.Println("Hour: ", t.Hour())
	}
}
xxx
Hour:  12

for

Basis

package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}
45

Use as while

package main

import "fmt"

func main() {
	sum := 1
	for sum < 20 {
		sum += sum
		fmt.Println(sum)
	}
	fmt.Println(sum)
}
2
4
8
16
32
32

range|Array, Slice

package main

import "fmt"

func main() {
	s := []string{"aaa", "bbb", "ccc"}

	for i, v := range s {
		fmt.Printf("index: %d  value: %v\n", i, v)
	}
}
index: 0  value: aaa
index: 1  value: bbb
index: 2  value: ccc

range|map

package main

import "fmt"

func main() {
	m := map[string]int{
		"aaa": 100,
		"bbb": 200,
		"ccc": 300,
	}

	for k, v := range m {
		fmt.Printf("key: %v  value: %v\n", k, v)
	}
}
key: aaa  value: 100
key: bbb  value: 200
key: ccc  value: 300

range|string

package main

import "fmt"

func main() {
	s := "わくわくBank"

	for i, v := range s {
		fmt.Printf("%T i:%v v:%v\n", v, i, v)
	}
}
int32 i:0 v:12431
int32 i:3 v:12367
int32 i:6 v:12431
int32 i:9 v:12367
int32 i:12 v:66
int32 i:13 v:97
int32 i:14 v:110
int32 i:15 v:107

break

package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		fmt.Printf("i: %d\n", i)

		for j := 0; j < 3; j++ {
			fmt.Printf("j: %d\n", j)
			if j == 2 {
				fmt.Println("inner loop")
				break
			}
		}

		if i == 2 {
			fmt.Println("outer loop")
			break
		}
	}
	fmt.Println("done")
}
i: 0
j: 0
j: 1
j: 2
inner loop
i: 1
j: 0
j: 1
j: 2
inner loop
i: 2
j: 0
j: 1
j: 2
inner loop
outer loop
done

break label

package main

import "fmt"

func main() {
OuterLoop:
	for i := 0; i < 3; i++ {
		fmt.Printf("i: %d\n", i)

		for j := 0; j < 3; j++ {
			fmt.Printf("j: %d\n", j)
			if j == 2 {
				fmt.Println("inner loop")
				break OuterLoop
			}
		}

		if i == 2 {
			fmt.Println("outer loop")
			break
		}
	}
	fmt.Println("done")
}
i: 0
j: 0
j: 1
j: 2
inner loop
done

continue

package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		fmt.Printf("i: %d\n", i)

		for j := 0; j < 3; j++ {
			fmt.Printf("j: %d\n", j)
			if j == 2 {
				fmt.Println("inner loop")
				continue
			}
		}

		if i == 2 {
			fmt.Println("outer loop")
			continue
		}
	}
	fmt.Println("done")
}
i: 0
j: 0
j: 1
j: 2
inner loop
i: 1
j: 0
j: 1
j: 2
inner loop
i: 2
j: 0
j: 1
j: 2
inner loop
outer loop
done

continue label

package main

import "fmt"

func main() {
OuterLoop:
	for i := 0; i < 3; i++ {
		fmt.Printf("i: %d\n", i)

		for j := 0; j < 3; j++ {
			fmt.Printf("j: %d\n", j)
			if j == 2 {
				fmt.Println("inner loop")
				continue OuterLoop
			}
		}

		if i == 2 {
			fmt.Println("outer loop")
			continue
		}
	}
	fmt.Println("done")
}
i: 0
j: 0
j: 1
j: 2
inner loop
i: 1
j: 0
j: 1
j: 2
inner loop
i: 2
j: 0
j: 1
j: 2
inner loop
done

switch

Usage Example 1

break is not required.

package main

import (
	"fmt"
)

func main() {
	s := "bbb"
	switch s {
	case "aaa":
		fmt.Println("case aaa")
	case "bbb":
		fmt.Println("case bbb")
	default:
		fmt.Println("case default")
	}
}
case bbb

Usage Example 2

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Println(runtime.NumCPU())

	switch {
	case runtime.NumCPU() < 8:
		fmt.Println("case runtime.NumCPU() < 8")
	case runtime.NumCPU() < 16:
		fmt.Println("case runtime.NumCPU() < 16")
	case runtime.NumCPU() < 32:
		fmt.Println("case runtime.NumCPU() < 32")
	case runtime.NumCPU() < 32:
		fmt.Println("case runtime.NumCPU() < 64")
	default:
		fmt.Println("case default")
	}
}
16
case runtime.NumCPU() < 32

Usage Example 3

package main

import (
	"fmt"
)

func main() {
	var i interface{} = "hello"

	switch v := i.(type) {
	case int:
		fmt.Printf("%v is int[%T]\n", v, v)
	case string:
		fmt.Printf("%v is string[%T]\n", v, v)
	default:
		fmt.Printf("default: %v[%T]\n", v, v)
	}
}
hello is string[string]

defer

The processing specified by defer is executed after the function has been processed.

package main

import "fmt"

func main() {
	defer fmt.Println("world1")
	defer fmt.Println("world2")

	fmt.Println("hello")
}
hello
world2
world1

Be careful when using it in a method chain. Here is an example.

package main

import "fmt"

type deferTest int

func (t *deferTest) func1() *deferTest {
	fmt.Println("func1")
	return t
}

func (t *deferTest) func2() *deferTest {
	fmt.Println("func2")
	return t
}

func (t *deferTest) func3() *deferTest {
	fmt.Println("func3")
	return t
}

func main() {
	var dt deferTest
	defer dt.func1().func2().func3()

	fmt.Println("main func")
}
func1
func2
main func
func3

select

When processing multiple channels in parallel, the control syntax select can be utilized.

package main

import (
	"fmt"
	"time"
)

func test1(ch chan<- string) {
	for {
		ch <- "test1"
		time.Sleep(2 * time.Second)
	}
}

func test2(ch chan<- string) {
	for {
		ch <- "test2"
		time.Sleep(4 * time.Second)
	}
}

func test3(quit chan<- int) {
	time.Sleep(10 * time.Second)
	quit <- 0
}

func main() {
	c1 := make(chan string)
	c2 := make(chan string)
	quit := make(chan int)
	go test1(c1)
	go test2(c2)
	go test3(quit)

	cnt := 0
	for {
		select {
		case s1 := <-c1:
			fmt.Println(s1)
		case s2 := <-c2:
			fmt.Println(s2)
		case <-quit:
			fmt.Println("quit")
			return
		default:
			cnt = cnt + 1
			fmt.Printf("(cnt: %v)\n", cnt)
			time.Sleep(1 * time.Second)
		}
	}
}
(cnt: 1)
test1
test2
(cnt: 2)
(cnt: 3)
(cnt: 4)
test1
(cnt: 5)
test2
(cnt: 6)
(cnt: 7)
test1
(cnt: 8)
(cnt: 9)
test1
test2
(cnt: 10)
quit

Scope

Explicit Blocks

A Block can be declared by enclosing it in { } (curly braces) to separate the scopes.

package main

import (
	"fmt"
)

func main() {
	x := 1
	y := 2

	// Declare Block
	{
		x = 10
		y := 20
		z := 30
		fmt.Printf("x = %v\n", x)
		fmt.Printf("y = %v\n", y)
		fmt.Printf("z = %v\n", z)
	}

	// Overwritten in the Block, so it will be 10.
	fmt.Printf("x = %v\n", x)

	// 2 as it is different from y defined in the Block.
	fmt.Printf("y = %v\n", y)

	// z is defined only in Block, so it is not available here.
	//fmt.Printf("z = %v\n", z)
}
x = 10
y = 20
z = 30
x = 10
y = 2

Implicit Block

The “if for switch declaration” and “each clause of switch select” are implicitly considered blocks and separate scopes.

Reference

Let's share this post !
TOC