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.