Go勉強記録

# 文法
まずは単純な出力
```golang
func main () {
    fmt.Println()
}
```
```golang
var i (型) = (値) //関数の内外どちらでも書くことができる
xi := (値) //こちらの場合は関数の中でのみ書くことができる
var (
    float64 = (値)
    int = (値)
    string = (値)
) //一度にたくさんの文字を定義することができる
```
で定義することができる

```golang
fmt.Printf("%T", i)
fmt.Printf("%T\n", i) //こちらを実行すると型を出力した後に改行をする
```
iの型を調べることができる

### const
```golang
const Pi = 3.14
const (
    Username = "test_user"
    Password = "test_pass"
)
```
書き換えることができない

### シフト演算子について
```golang
fmt.Println(1 << 0) // 0001 0001
fmt.Println(1 << 1) // 0001 0010
fmt.Println(1 << 2) // 0001 0100
fmt.Println(1 << 3) // 0001 1000
```
### 配列の宣言方法
```golang
var (変数) [配列の大きさ](型)
var a [2]int
var b [2]int = [2]int{100, 200}
```
:::note
配列はサイズ変更はできない
:::

### スライス(サイズ変更できる)の宣言方法
```golang
var a []int = []int{100, 200}
a = append(a, 300)
fmt.Println(b)
```
```console
[100, 200, 300]
```
スライスは大きさを変更できる

### 二次配列
```golang
var board = [][]int{
    []int{0, 1, 2}
    []int{3, 4, 5}
    []int{6, 7, 8}
}
fmt.Println(board)
```
```console
[[0, 1, 2] [4, 5, 6] [7, 8, 9]]
```

### スライスのmakeとcap
```golang
func main() {
    n := make([]int, 3, 5)
    fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n)
    n = append(n, 0, 0)
    fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n)
    n = append(n, 1, 2, 3)
    fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n)
```

```console
len=3 cap=5 value=[0 0 0]
len=5 cap=5 value=[0 0 0 0 0]
len=10 cap=10 value=[0 0 0 0 0 1 2 3]
```

### map
```golang
m := map[string]int{"apple": 100, "banana": 200}
fmt.Println(m)
fmt.Println(m["apple"])
```

```golang
v, ok := m["apple"]
fmt.Println(v, ok)
v2, ok2 := m["nothing"]
fmt.Println(v2, ok2)
```
```console
100 true
0 false
```

### if文の書き方
```golang
x, y := 10, 10
fi x == 10 && y == 10{
    fmt.Println("&&") //AND
} else if x == 10 || y == 10{
    fmt.Println("||") //OR
}
```

### if文を簡略化して書く方法
```golang
if (値の代入); (条件式){
    何らかの処理
} //値の代入で設定した変数はif文の中でしか使用できない
```

### for文の書き方
```golang
for i := 0; i < 10; i++{
    if i == 3{
        continue
    } //continueは実行されずに次のループへ行く
    fmt.Println(i)
}
```

### range
```golang
l := []string{"python", "go", "java"}
for i, v := range l{
    fmt.Println(i, v)
}
m := map[string]int{"apple":100, "banana":200}
for k := range m{
    fmt.Println(k)
} 
//mapはkeyを取り出さないようにすることができる、
//valueのみを取り出したいときは_, v :=とすればよい 
```
出力は以下のようになる
```console
0 python
1 go
2 java
apple
banana
```

### switch文
```golang
os := "mac"
switch os {　//switch os := getOsName(); os { ←こちらの場合だとswitchないのみでosが有効
case "mac":
    fmt.Println("mac")
case "windows":
    fmt.Println("windows")
default:
    fmt.Println("default") //なくてもよい
```

### defer
関数が終わった後に実行される
```golang
func main() {
    defer fmt.Println("world")
    fmt.Println("hello")
}
```
```console
hello
world
```
最初に入れたものが最後に実行される
```golang
func main() {
    fmt.Println("run")
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    fmt.Println("success")
```
```console
run
success
3
2
1
```

### log
このようなエラー処理ができる
```golang
_, err := os.Open("fjdksj")
if err != nil{
    log.Fataln("Exit", err)
}
```
ログをファイルに書き込む方法↓
```golang
func LoggingSettings(logFile string){
    logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    multilogFile := io.MultiWriter(os.Stdout, logfile)
    log.SetFlags(log.Ldate|log.Ltime|log.Lshortfile)
    log.SetOutput(multiLogFile)
}
```
```golang
logfile, err := os.OpenFile() //ファイルのオープン
multilofFile := io.MultiWriter(  ,  ) //ログの出力先を複数に
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) //ログフォーマットの設定
log.SetOutput(multlogFile) //ログ出力先設定
```

### エラーハンドリング
```golang
file, err := os.Open("./)
if err != nil{    //エラー出なければerrにはnilが入る
    log.Fatalln("error")    
} //goにはtry-catchがない
data := make([]byte, 100)
count, err := file.Read(data) 
//:=は左側の何かを一つでもinitializeすればエラーにならないのでerrを上書きしているif err != nil{
    log.Fatalln("error")
}
```

### panicとrecover
```golang
func thirdPartyConnectDB(){
    panic("unable to connect database") //自分で例外を投げることができる(強制終了)
}

func save(){
    thirdPartyConnectDB()
}

func main(){
    save()
    fmt.Print("ok")
}
```
```panic```は```recover()```でキャッチすることができる
```panic```はなるべく書かないようにする