---
# System prepended metadata

title: 'Day07 Go飆車囉-狂教基本語法(if, switch, for, log)'

---

# Day07 Go飆車囉-狂教基本語法(if, switch, for, log)

今天東西稍微多了點，  
但忍耐一下，文章就快結束了。  

各程式語言基本上大同小異  
如果各位學過其他程式語言、已有程式底子，  
那麼學`Golang`只剩下**適應Go的語法**。  
>
> 但是學習嘛，想是一回事、做是一回事  
> 看完文章別看過就好，還是要自己動手從零開始的打異世界程式  
>
> 俗話說的好：學程式別無他法，唯有自己寫，才是自己的。  
> 
> 法二：找個工具人 


## 語法斷句
    
在Go中，語法斷句需要分號`;` **但是你不用寫**（硬要寫也是可以啦）。  
因為它會幫你產生，可以省鍵盤軸心壽命，夠佛。  

> Like C, Go's formal grammar uses semicolons to terminate statements, 
> but unlike in C, those semicolons do not appear in the source.

```go
a := 10;
b := 20;;
fmt.Println(a, b);;;;;
```

## 條件判斷

#### 【if 條件】

條件直接寫，不用加小括號  
（要加也是可以啦，不會報錯，佛心公司）  
```go
if Condition {
	...
} else {
    ...
}
```

https://play.golang.org/p/DW0nTIuHWnk  



#### 【Switch】

一次做多個`if`的判斷  
可以把**條件代入`case`中，也可以放在`switch`上，**
一魚可以兩吃，佛心公司。  
`case`跟`case`之間**不用`break`**，更加直觀，佛！  

https://play.golang.org/p/hRVHoeW6_h9
```go
var i int = 2
switch i {
case 1:
	fmt.Println("i is 1")
case 2:
	fmt.Println("i is 2")
case 3:
	fmt.Println("i is 3")
default:
	fmt.Println("i is not 1, 2, 3")

}
//--------
var j int = 10
switch {
case j == 1:
	fmt.Println("j is 1")
case j == 2:
	fmt.Println("j is 2")
case j == 3:
	fmt.Println("j is 3")
default:
	fmt.Println("j is not 1, 2, 3")
}
```


## 迴圈
#### 【for迴圈】
`for loop` 完全不用小括號，省時省力，佛！  
	
> **for Expression; Condition; Operation {  
> ...  
> }**  

https://play.golang.org/p/o4EZytZSgt-
```go
for i:=0; i<10; i++{
	fmt.Println(i)
}
```
#### 【while迴圈】
`Go` 沒有`While`關鍵字啦！記者標題！  
但可以這樣用  
> **for Condifion{  
> ...  
> }**  
https://play.golang.org/p/xVLC_SsygHt
```go
i := 0
for i < 10{
	fmt.Println(i)
	i++
}
```

#### 【for迭代】
能夠遍歷整個物件變數，  
另外用`for`迭代的話，就不能在裡頭**修改（新增、刪除）迭代物件**，會容易出問題  
若真要修改物件，請用上面**for迴圈**的方式  
> **for a, b := range Iterable{  
> ...  
> }**  


https://play.golang.org/p/2N6FrtbpB6f
```go
nums := []int{100, 99, 98}
for index, num := range nums {
	fmt.Println(index, num)
}
for index := range nums {
	fmt.Println(index)
}

//--------

fruits := map[string]string{"a": "apple", "b": "banana"}
for index, fruit := range fruits {
	fmt.Println(index, fruit)
}
for index := range fruits {
	fmt.Println(index)
}
```
單單一個`for`關鍵字有這麼多用途，佛！  

## Log日誌
#### 【log.Print】
#### 【log.Println】
#### 【log.Printf】
Go的`log.Print`用法跟`fmt.Print`用法基本上一致  
但`log`會在開一個線程出來，而`fmt`則是運行在主線程上  

```go
func main()  {
	for i:= 0; i <= 3; i++{
		log.Println(i)
		fmt.Println(i)
		// time.Sleep(time.Millisecond * 10)
		log.Println("hi")
		fmt.Println("hi")
	}

}
```

> 開線程這點在Windows的環境上看的出來（左）；但在Playground及MacOS中運行起來是這樣（右）
> ![Win10 vs MaxOS](https://i.imgur.com/33b1WBZ.png)



#### 【log.SetFlag】
改變印出的時間格式  
```go
log.SetFlags(0)
log.SetFlags(1)    2020/09/13 
log.SetFlags(2)    20:57:00
log.SetFlags(3)    2020/09/13 20:57:00
log.SetFlags(4)    20:57:00.862816
log.SetFlags(5)    2020/09/13 20:57:00.862816
```

也可以用常數名稱直接帶入`log.SetFlags(log.Ldate)` 
關於SetFlags的參數  
```go
const (
	Ldate         = 1 << iota     // local time zone: 2009/01/23
	Ltime               //2       // local time zone: 01:23:23
	Lmicroseconds       //4       // microsecond : 01:23:23.123123.
	Llongfile           //8       // full filename, line: /a/b/c/d.go:23
	Lshortfile          //16      // filename element, line: d.go:23
	LUTC                //32      // use UTC
	Lmsgprefix          //64      // move the "prefix" from the beginning of the line to before the message  
	LstdFlags     = Ldate | Ltime    //3 預設Flag // initial standard logger
)
```

若想要同時印出 檔案名稱 `Lshortfile (16)` 及 日期 `Ldate(1)`，  
則可直接相加數字，設定為`log.SetFlags(17)`，以此類推。  
也可以用`|` **（或運算or）** `log.SetFlags(log.Lmsgprefix | log.LstdFlags)`  

格式可以自己兜，任君挑選，**佛！**    
https://play.golang.org/p/IIoJo55I8sr   
```go
import (
	"log"
)

func main() {
	for i := 0; i <= 127; i++ {
		log.SetFlags(i)
		log.Print("log.SetFlags(", i, ")")
	}

}
```

#### 【log.SetPrefix】
```go
log.SetPrefix("文字")
```
https://play.golang.org/p/gwCz6XNkjDx  

``` go
func main()  {
	log.SetPrefix("安安，我是log ")
	log.Println("Hi")
	log.Fatalln("發生錯誤")
}

/* result:
安安，我是log 2009/11/10 23:00:00 Hi
安安，我是log 2009/11/10 23:00:00 發生錯誤
*/
```


#### 【log.Fatal】
#### 【log.Fatalf】
#### 【log.Fatalln】
用於發生錯誤時印出log並退出  
點進去看go原始碼，退出的實作是多了`os.Exit(1)`這行   

```go
func Fatal(v ...interface{}) {
	std.Output(2, fmt.Sprint(v...))
	os.Exit(1)
}
```

要自製logger，[可以參考此處](https://golang.org/pkg/log/#Logger)   
