Goで地味だけど知っておいて損はないこと

## マップ編
- マップにおいて、最後の要素の後にも","をつける(つけないとsyntax error、下の例もエラー)。

```golang
	students := map[string]int{
		"jon": 12,
		"bob": 34
	}
```
- キーの存在確認をしたいときは返ってくる２つ目の値を使う。

```golang
	students := map[string]int{
		"jon": 12,
		"bob": 34,
	}
	age1, ok1 := students["jon"] 
	fmt.Println(age1, ok1) // 12 true
	age2, ok2 := students["alice"] 
	fmt.Println(age2, ok2) // 0 false 
```
## JSON編
- json.Marshalでマーシャリングされるのは公開されているフィールドだけ(以下の例だとageが出力しない)。
- json.MarshalIndentを使うと人間が見やすいようにインデントしてくれる。

```golang
type User struct {
	Name    string
	age     int
	Address string
}

func main() {
	var users = []User{
		{Name: "bob", age: 12, Address: "Tokyo"},
		{Name: "jon", age: 23, Address: "Kyoto"},
	}
	data, err := json.Marshal(users)
	if err != nil {
		log.Fatalf("JSON marshaling failed: %s", err)
	}
	dataIndent, err := json.MarshalIndent(users, "", "   ")
	if err != nil {
		log.Fatalf("JSON marshaling failed: %s", err)
	}
	fmt.Printf("%s\n", data)
	fmt.Printf("%s\n", dataIndent)
}
```

- 型の定義の後に \`json:"~"\` と書くと、json.Marshalした際に~で指定した名称になる。  
さらにomitemptyをオプションでつけると、フィールドがその型のゼロ値(以下の例ではfalse)または空の場合JSONの出力をしない。

```golang

type User struct {
	Name    string `json:"username"`
	Age     int
	Address string
	Admin   bool `json:"admin_user,omitempty"`
}

=>
[{"username":"bob","Age":12,"Address":"Tokyo","admin_user":true},{"username":"jon","Age":23,"Address":"Kyoto"}]

```

## 関数編
- Goには、他の言語にあるようなキーワード引数やデフォルト引数はない。
- 引数は値渡しなので、関数はそれぞれの引数のコピーを受け取るため、コピーに対する修正は呼び出し元には影響しない。  
※ポインタ、スライス、マップ等を使えば間接的に呼び出し元が修正を受ける場合もある。

- 可変個引数の関数を定義する場合は、最後のパラメータの型の前に省略記号の"..."をつける。

```golang
func main() {
	fmt.Println(sum(1, 2, 3, 4, 5))
}

func sum(numbers ...int) int {
	total := 0
	for _, num := range numbers {
		total += num
	}
	return total
}
```


## メソッド編
- setXYメソッドは*Pointレシーバを要求する場合、下記の2つの出力は同じになる。  
これは2つめの例ではコンパイラが変数に対して暗黙的に&pを行なっているためです。

```golang
type Point struct{ X, Y int }

func main() {
	p := Point{1, 1}
	(&p).setXY(2, 3)
	fmt.Println(p) // {2 3}
}

func (p *Point) setXY(x, y int) {
	p.X = x
	p.Y = y
}
```
```golang
type Point struct{ X, Y int }

func main() {
	p := Point{1, 1}
	p.setXY(2, 3)  // 暗黙的に&pが行われる
	fmt.Println(p) // {2 3}
}

func (p *Point) setXY(x, y int) {
	p.X = x
	p.Y = y
}
```

## チャネル編
### バッファなしチャネル
- チャネルを介してメッセージを送信する際、追加の情報を保持していない、  
つまり目的が同期のみである場合には要素型が struct{} であるチャネルを使ってその点を強調する。

```golang
// チャネルの定義
ch := make(chan struct{})

// 送信側
ch <- struct{}{}

// 受信側
<-ch // 受信結果は破棄している
```

- チャネルを引数として使用する関数やメソッドにおいて、そのチャネルが受信専用、送信専用の場合は、  
受信専用は `<変数> <-chan <型>`, 送信専用は `<変数> chan<- <型>`とすることで、  
受信用のチャネルが送信に、送信用のチャネルが受信に使わる場合にコンパイルエラーとして検出できる。


```golang
func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)

	go first(ch1)
	go second(ch1, ch2)
	third(ch2)
}

func first(out chan<- int) {
	x := 100
	out <- x
}

func second(in <-chan int, out chan<- int) {
	x := <-in
	out <- x + 1
}

func third(in <-chan int) {
	fmt.Println(<-in) // 101
}
```
コンパイルエラーにならないバージョン: https://play.golang.org/p/niSG6MZHcpy
コンパイルエラーになるバージョン: https://play.golang.org/p/WUgtBO6i2Ei

### バッファありチャネル
- バッファありチャネルのバッファ容量を知りたい場合は `cap` 、現在バッファされている要素の個数は `len`を使用する。

```golang
func main() {
	ch := make(chan int, 3)
	ch <- 1
	ch <- 2
	fmt.Printf("cap(ch) = %d\n", cap(ch)) // cap(ch) = 3
	fmt.Printf("len(ch) = %d\n", len(ch)) // len(ch) = 2
}
```
https://play.golang.org/p/53nGGUdUo-Z

## その他
- Goを使用していると、以下のようなerrへの省略変数宣言(:=)をよく使用するが、  
必ずしも左辺の全ての変数を宣言するわけでなく、以下の例ではerrが2回目に使われる部分では  
変数宣言ではなく変数への"代入"になる。  
ただし、左辺が両方とも代入になる場合はコンパイルエラーになるので、必ず1つは新たに変数宣言される必要がある。

```golang
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

    ・・・

	doc, err := html.Parse(os.Stdin)
	if err != nil {
           (略)
	}
```