【初中級編】Go言語を始める方のための落とし穴、問題の解決方法やよくある間違い

こちらの記事は、Kyle Quest氏により公開された『[50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs](http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html)』の和訳です。
本記事は原著者から許可を得た上で記事を公開しています。

初心者(Total Beginner)向けの和訳は [【初級編】Go言語を始める方のための落とし穴、問題の解決方法やよくある間違い](https://medium.com/eureka-engineering/go-beginner-3bb95e0790da) があります。本記事は初中級者(Intermediate Beginner)向けの和訳です。

---

## 初中級者向け

<!-- no toc -->
* [HTTPレスポンスボディのクローズ](#httpレスポンスボディのクローズ)
* [HTTPコネクションのクローズ](#httpコネクションのクローズ)
* [JSONエンコーダーが追加する改行](#jsonエンコーダーが追加する改行)
* [JSONパッケージによるキーと文字列値の特別なHTML文字のエスケープ](#jsonパッケージによるキーと文字列値の特別なhtml文字のエスケープ)
* [JSON数値のインターフェース型へのデコード](#json数値のインターフェース型へのデコード)
* [16進数や非UTF8のエスケープシーケンスがJSON文字列値として使えない](#16進数や非utf8のエスケープシーケンスがjson文字列値として使えない)
* [構造体、配列、スライス、マップの比較](#構造体配列スライスマップの比較)
* [panicの回復](#panicの回復)
* [スライス、配列、マップの"for-range"句での項目の更新と参照](#スライス配列マップのfor-range句での項目の更新と参照)
* [スライスの"隠れた"データ](#スライスの隠れたデータ)
* [スライスデータの"破損"](#スライスデータの破損)
* ["古く"なるスライス](#古くなるスライス)
* [型宣言とメソッド](#型宣言とメソッド)
* ["for-switch"や"for-select"のコードブロックにおけるbreak](#for-switchやfor-selectのコードブロックにおけるbreak)
* ["for"文の中のイテレーション変数とクロージャ](#for文の中のイテレーション変数とクロージャ)
* [遅延関数呼び出しの引数評価](#遅延関数呼び出しの引数評価)
* [遅延関数呼び出しの実行](#遅延関数呼び出しの実行)
* [型アサーションの失敗](#型アサーションの失敗)
* [ブロックされるgoroutineとリソースリーク](#ブロックされるgoroutineとリソースリーク)
* [異なるサイズ0の変数が同じアドレスになる](#異なるサイズ0の変数が同じアドレスになる)
* [iotaの始まりが常に0になるわけではない](#iotaの始まりが常に0になるわけではない)

### HTTPレスポンスボディのクローズ

<!-- When you make requests using the standard http library you get a http response variable. If you don't read the response body you still need to close it. Note that you must do it for empty responses too. It's very easy to forget especially for new Go developers.

Some new Go developers do try to close the response body, but they do it in the wrong place. -->

標準のhttpライブラリを使ってリクエストをすると、HTTPレスポンスの変数を取得します。レスポンスボディを読まない場合でも、レスポンスボディをクローズする必要があります。また空のレスポンスに対してもレスポンスボディをクローズする必要があることに注意してください。新米Gopherにとっては特に忘れやすい内容です。

同様に間違った場所でレスポンスボディをクローズしようとする人がいます。

```go
package main

import (  
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {  
    resp, err := http.Get("https://api.ipify.org?format=json")
    defer resp.Body.Close()//問題があります
    if err != nil {
        fmt.Println(err)
        return
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(body))
}
```

<!-- This code works for successful requests, but if the http request fails the `resp` variable might be nil, which will cause a runtime panic.

The most common why to close the response body is by using a defer call after the http response error check. -->

上記のコードはリクエストが成功した場合には動作しますが、HTTPリクエストが失敗した場合には `resp` 変数が `nil` になる可能性があり、実行時にpanicが起きます。

HTTPレスポンスがエラーかどうかチェックしたあとに `defer` を使ってレスポンスボディをクローズするのが一般的な作法です。

```go
package main

import (  
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {  
    resp, err := http.Get("https://api.ipify.org?format=json")
    if err != nil {
        fmt.Println(err)
        return
    }

    defer resp.Body.Close()//ほとんどの場合は問題ないでしょう
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(body))
}
```

<!-- Most of the time when your http request fails the `resp` variable will be `nil` and the `err` variable will be `non-nil`. However, when you get a redirection failure both variables will be `non-nil`. This means you can still end up with a leak.

You can fix this leak by adding a call to close `non-nil` response bodies in the http response error handling block. Another option is to use one `defer` call to close response bodies for all failed and successful requests. -->

HTTPリクエストが失敗したほとんどの場合、変数 `resp` は `nil` になり変数 `err` は `non-nil` となるでしょう。しかし、リダイレクトに失敗した場合は両方の変数が `non-nil` になりえます。この場合はリソースのリークが発生する可能性があります。

HTTPレスポンスをエラーハンドリングするブロックの中で `non-nil` であるレスポンスボディをクローズすることで、上記のリークを防ぐことができます。もう一つの方法は、リクエストが成功したか失敗したかにかかわらず、レスポンスボディをクローズするように `defer` を使って呼び出すことです。

```go
package main

import (  
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {  
    resp, err := http.Get("https://api.ipify.org?format=json")
    if resp != nil {
        defer resp.Body.Close()
    }

    if err != nil {
        fmt.Println(err)
        return
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(body))
}
```

<!-- The orignal implementation for `resp.Body.Close()` also reads and discards the remaining response body data. This ensured that the http connection could be reused for another request if the keepalive http connection behavior is enabled. The latest http client behavior is different. Now it's your responsibility to read and discard the remaining response data. If you don't do it the http connection might be closed instead of being reused. This little gotcha is supposed to be documented in Go 1.5. -->

当初の `resp.Body.Close()` の実装では、残りのレスポンスボディのデータを読み込んで破棄していました。これはHTTP Keep-Aliveを有効にしておけば、HTTPコネクションを別のリクエストで再利用することを保証していました。最新のHTTPクライアントでは異なります。残りのレスポンスデータを読み込んで破棄するのは、クライアントの責務です。そうしない場合、HTTPコネクションは再利用されずに、クローズされるかもしれません。この小さな落とし穴はGo 1.5でドキュメントに書かれることになっています。

<!-- If reusing the http connection is important for your application you might need to add something like this at the end of your response processing logic: -->

アプリケーションにとってHTTPコネクションの再利用が重要な場合、HTTPレスポンスを処理するロジックの最後に以下のような実装を追加する必要があるかもしれません。

```go
_, err = io.Copy(ioutil.Discard, resp.Body)  
```

<!-- It will be necessary if you don't read the entire response body right away, which might happen if you are processing json API responses with code like this: -->

以下のようなコードでJSONのAPIレスポンスを処理している場合には、すぐにレスポンスボディ全体を読まない場合があるため、上記のようなコードが必要になります。

```go
json.NewDecoder(resp.Body).Decode(&data)  
```

### HTTPコネクションのクローズ

<!-- Some HTTP servers keep network connections open for a while (based on the HTTP 1.1 spec and the server "keep-alive" configurations). By default, the standard http library will close the network connections only when the target HTTP server asks for it. This means your app may run out of sockets/file descriptors under certain conditions. -->

いくつかのHTTPサーバはしばらくの間ネットワーク接続をオープンし続けます(HTTP 1.1 の仕様とサーバの "keep-alive" の設定に基づいています)。デフォルトでは、標準のhttpライブラリは接続先のHTTPサーバが要求した場合にのみネットワーク接続をクローズします。これは特定の状況下において、ソケットやファイルディスクリプションを使い果たす可能性があります。

<!-- You can ask the http library to close the connection after your request is done by setting the `Close` field in the request variable to `true`. -->

リクエスト変数の `Close` フィールドを `true` にセットすることで、リクエストが完了した後に接続をクローズするようにhttpライブラリに依頼できます。

<!-- Another option is to add a `Connection` request header and set it to `close`. The target HTTP server should respond with a `Connection: close` header too. When the http library sees this response header it will also close the connection. -->

もう一つの方法は、リクエストヘッダーの `Connection` に `close` をセットしてリクエストすることです。ターゲットのHTTPサーバもレスポンスヘッダーに `Connection: close` を付与してレスポンスしなければなりません。httpライブラリがこのレスポンスヘッダーを見ると、コネクションをクローズします。 

```go
package main

import (  
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {  
    req, err := http.NewRequest("GET","http://golang.org",nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    req.Close = true
    //あるいは以下のようにします:
    //req.Header.Add("Connection", "close")

    resp, err := http.DefaultClient.Do(req)
    if resp != nil {
        defer resp.Body.Close()
    }

    if err != nil {
        fmt.Println(err)
        return
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(len(string(body)))
}
```

<!-- You can also disable http connection reuse globally. You'll need to create a custom http transport configuration for it. -->

httpライブラリのtransportの設定をカスタマイズすることで、HTTPコネクションが再利用されることをグローバルに無効化することもできます。

```go
package main

import (  
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {  
    tr := &http.Transport{DisableKeepAlives: true}
    client := &http.Client{Transport: tr}

    resp, err := client.Get("http://golang.org")
    if resp != nil {
        defer resp.Body.Close()
    }

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(resp.StatusCode)

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(len(string(body)))
}
```

<!-- If you send a lot of requests to the same HTTP server it's ok to keep the network connection open. However, if your app sends one or two requests to many different HTTP servers in a short period of time it's a good idea to close the network connections right after your app receives the responses. Increasing the open file limit might be a good idea too. The correct solution depends on your application though. -->

同じHTTPサーバに多くのリクエストを送信する場合、ネットワーク接続をオープンにしたままでも問題ありません。しかし、短い間隔で異なるHTTPサーバに1、2つのリクエストを送信する場合、レスポンスを受け取った後すぐにネットワーク接続をクローズすることは良い考えです。同様にオープンできるファイルの制限数を増やしておくことも良い考えでしょう。いずれにしても、正しい解決策はアプリケーションに依存します。

### JSONエンコーダーが追加する改行

<!-- You are writing a test for your JSON encoding function when you discover that your tests fail because you are not getting the expected value. What happened? If you are using the JSON Encoder object then you'll get an extra newline character at the end of your encoded JSON object. -->

JSONをエンコードするテストを実装していたときに、期待した値を取得できずにテストが失敗したことに気が付きました。何が起きたのでしょう。JSONエンコーダーを使っている場合、JSONエンコードした値の最後に改行文字が追加されます。

```go
package main

import (
  "fmt"
  "encoding/json"
  "bytes"
)

func main() {
  data := map[string]int{"key": 1}
  
  var b bytes.Buffer
  json.NewEncoder(&b).Encode(data)

  raw,_ := json.Marshal(data)
  
  if b.String() == string(raw) {
    fmt.Println("same encoded data")
  } else {
    fmt.Printf("'%s' != '%s'\n",raw,b.String())
    //prints:
    //'{"key":1}' != '{"key":1}\n'
  }
}
```

<!-- The JSON Encoder object is designed for streaming. Streaming with JSON usually means newline delimited JSON objects and this is why the Encode method adds a newline character. This is a documented behavior, but it's commonly overlooked or forgotten. -->

JSONエンコーダーはストリーミング用に設計されています。JSONのストリーミングは通常、改行で区切られたJSONオブジェクトです。Encodeメソッドが改行文字を追加するのはこのためです。これはドキュメントに書いてある動作ですが、見落としたり忘れがちです。

### JSONパッケージによるキーと文字列値の特別なHTML文字のエスケープ

<!-- This is a documented behavior, but you have to be careful reading all of the JSON package documentation to learn about it. The `SetEscapeHTML` method description talks about the default encoding behavior for the and, less than and greater than characters. -->

これはドキュメントに書いてある動作ですが、知るためにはJSONパッケージのすべてのドキュメントを注意深く読まなくてはなりません。`SetEscapeHTML` メソッドの説明では `&`, `<`, `>` の文字のデフォルトのエンコーディング動作について説明しています。

<!-- This is a very unfortunate design decision by the Go team for a number of reasons. First, you can't disable this behavior for the `json.Marshal` calls. Second, this is a badly implemented security feature because it assumes that doing HTML encoding is sufficient to protect against XSS vulnerabilities in all web applications. There are a lot of different contexts where the data can be used and each context requires its own encoding method. And finally, it's bad because it assumes that the primary use case for JSON is a web page, which breaks the configuration libraries and the REST/HTTP APIs by default. -->

これはGoチームによる非常に残念な設計上の決定です。いくつか理由があります。第一に、`json.Marshal` の呼び出しではこの動作を無効にすることはできません。第二に、すべてのWebアプリケーションをXSSの脆弱性から保護するためには、HTMLエンコーディングを実施するだけで十分であると考えているため、セキュリティ的に実装が不十分な機能です。データが利用されるコンテキストはたくさんあり、それぞれのコンテキストで独自のエンコーディング方法を必要とします。そして最後に、JSONの主なユースケースがWebページであることを想定しているため、設定ライブラリやREST/HTTP APIをデフォルトで壊してしまう、という残念な点があります。

```go
package main

import (
  "fmt"
  "encoding/json"
  "bytes"
)

func main() {
  data := "x < y"
  
  raw,_ := json.Marshal(data)
  fmt.Println(string(raw))
  //prints: "x \u003c y" <- おそらく期待したものではないでしょう
  
  var b1 bytes.Buffer
  json.NewEncoder(&b1).Encode(data)
  fmt.Println(b1.String())
  //prints: "x \u003c y" <- おそらく期待したものではないでしょう
  
  var b2 bytes.Buffer
  enc := json.NewEncoder(&b2)
  enc.SetEscapeHTML(false)
  enc.Encode(data)
  fmt.Println(b2.String())
  //prints: "x < y" <- 良さそうですね
}
```

<!-- A suggestion to the Go team... Make it an opt-in. -->

Goチームへの提案... オプトインにしてください。

### JSON数値のインターフェース型へのデコード

<!-- By default, Go treats numeric values in JSON as float64 numbers when you decode/unmarshal JSON data into an interface. This means the following code will fail with a panic: -->

デフォルトでは、JSONデータをインターフェース型にデコード/アンマーシャルするときに、GoはJSONの中に含まれる数値を `float64` 型として扱います。以下のコードはpanicを起こして失敗します。

```go
package main

import (  
  "encoding/json"
  "fmt"
)

func main() {  
  var data = []byte(`{"status": 200}`)

  var result map[string]interface{}
  if err := json.Unmarshal(data, &result); err != nil {
    fmt.Println("error:", err)
    return
  }

  var status = result["status"].(int) //エラー
  fmt.Println("status value:",status)
}
```

<!-- Runtime Panic: -->
実行時panic:

> panic: interface conversion: interface is float64, not int

<!-- If the JSON value you are trying to decode is an integer you have serveral options. -->

デコードしようとしているJSONの値が整数の場合、いくつかの選択肢があります。

<!-- Option one: use the float value as-is :-) -->
選択肢1：浮動小数点の値をそのまま使う

<!-- Option two: convert the float value to the integer type you need. -->
選択肢2：浮動小数点の値を必要な整数型に変換する

```go
package main

import (  
  "encoding/json"
  "fmt"
)

func main() {  
  var data = []byte(`{"status": 200}`)

  var result map[string]interface{}
  if err := json.Unmarshal(data, &result); err != nil {
    fmt.Println("error:", err)
    return
  }

  var status = uint64(result["status"].(float64)) //ok
  fmt.Println("status value:",status)
}
```

<!-- Option three: use a `Decoder` type to unmarshal JSON and tell it to represent JSON numbers using the `Number` interface type. -->

選択肢3：JSONをアンマーシャルするために `Decoder` 型を使い、`Number` インターフェース型を使ってJSON数値を表現するように指示する

```go
package main

import (  
  "encoding/json"
  "bytes"
  "fmt"
)

func main() {  
  var data = []byte(`{"status": 200}`)

  var result map[string]interface{}
  var decoder = json.NewDecoder(bytes.NewReader(data))
  decoder.UseNumber()

  if err := decoder.Decode(&result); err != nil {
    fmt.Println("error:", err)
    return
  }

  var status,_ = result["status"].(json.Number).Int64() //ok
  fmt.Println("status value:",status)
}
```

<!-- You can use the string representation of your `Number` value to unmarshal it to a different numeric type: -->

Number型の文字列表現を使って、別の数値型にアンマーシャルすることができます。

```go
package main

import (  
  "encoding/json"
  "bytes"
  "fmt"
)

func main() {  
  var data = []byte(`{"status": 200}`)

  var result map[string]interface{}
  var decoder = json.NewDecoder(bytes.NewReader(data))
  decoder.UseNumber()

  if err := decoder.Decode(&result); err != nil {
    fmt.Println("error:", err)
    return
  }

  var status uint64
  if err := json.Unmarshal([]byte(result["status"].(json.Number).String()), &status); err != nil {
    fmt.Println("error:", err)
    return
  }

  fmt.Println("status value:",status)
}
```

<!-- Option four: use a `struct` type that maps your numeric value to the numeric type you need. -->

選択肢4：`struct` 型のフィールドに数値の値をマッピングしたい数値型を使う

```go
package main

import (  
  "encoding/json"
  "bytes"
  "fmt"
)

func main() {  
  var data = []byte(`{"status": 200}`)

  var result struct {
    Status uint64 `json:"status"`
  }

  if err := json.NewDecoder(bytes.NewReader(data)).Decode(&result); err != nil {
    fmt.Println("error:", err)
    return
  }

  fmt.Printf("result => %+v",result)
  //prints: result => {Status:200}
}
```

<!-- Option five: use a `struct` that maps your numeric value to the `json.RawMessage` type if you need to defer the value decoding. -->

選択肢5：値のデコードを後で実施する必要がある場合は、数値をマッピングする型として `json.RawMessage` 型を `struct` 型のフィールドに使う

<!-- This option is useful if you have to perform conditional JSON field decoding where the field type or structure might change. -->

この選択肢は条件によって型が変わったり構造が変わるJSONのフィールドをデコードをする必要があるときに便利です。

```go
package main

import (  
  "encoding/json"
  "bytes"
  "fmt"
)

func main() {  
  records := [][]byte{
    []byte(`{"status": 200, "tag":"one"}`),
    []byte(`{"status":"ok", "tag":"two"}`),
  }

  for idx, record := range records {
    var result struct {
      StatusCode uint64
      StatusName string
      Status json.RawMessage `json:"status"`
      Tag string             `json:"tag"`
    }

    if err := json.NewDecoder(bytes.NewReader(record)).Decode(&result); err != nil {
      fmt.Println("error:", err)
      return
    }

    var sstatus string
    if err := json.Unmarshal(result.Status, &sstatus); err == nil {
      result.StatusName = sstatus
    }

    var nstatus uint64
    if err := json.Unmarshal(result.Status, &nstatus); err == nil {
      result.StatusCode = nstatus
    }

    fmt.Printf("[%v] result => %+v\n",idx,result)
  }
}
```

### 16進数や非UTF8のエスケープシーケンスがJSON文字列値として使えない

<!-- Go expects string values to be UTF8 encoded. This means you can't have arbitrary hex escaped binary data in your JSON strings (and you also have to escape the backslash character). This is really a JSON gotcha Go inherited, but it happens often enough in Go apps that it makes sense to mention it anyways. -->

Goは文字列の値がUTF8でエンコードされていることを期待しています。つまりJSON文字列に16進数でエスケープされた任意のバイナリデータを含めることができません。(バックスラッシュ文字もエスケープしなければなりません)。実際にはGoが受け継いだJSONの問題ですが、本記事で言及するに値するほど、Goのアプリケーションでよく起こる問題です。

```go
package main

import (
  "fmt"
  "encoding/json"
)

type config struct {
  Data string `json:"data"`
}

func main() {
  raw := []byte(`{"data":"\xc2"}`)
  var decoded config

  if err := json.Unmarshal(raw, &decoded); err != nil {
        fmt.Println(err)
    //prints: invalid character 'x' in string escape code
    }
  
}
```

<!-- The Unmarshal/Decode calls will fail if Go sees a hex escape sequence. If you do need to have a backslash in you string make sure to escape it with another backlash. If you want to use hex encoded binary data you can escape the backslash and then do your own hex escaping with the decoded data in your JSON string. -->

16進数のエスケープシーケンスが含まれる場合、Unmarshal/Decodeの呼び出しは失敗します。文字列にバックスラッシュが必要な場合は、必ず別のバックスラッシュでエスケープしてください。16進数でエンコードされたバイナリデータを使いたい場合、バックスラッシュをエスケープしてから、JSON文字列内のデコードされたデータを使用して独自の16進数エスケープを行うことができます。

```go
package main

import (
  "fmt"
  "encoding/json"
)

type config struct {
  Data string `json:"data"`
}

func main() {
  raw := []byte(`{"data":"\\xc2"}`)
  
  var decoded config
  
  json.Unmarshal(raw, &decoded)
  
  fmt.Printf("%#v",decoded) //prints: main.config{Data:"\\xc2"}
  //todo: decoded.Dataに適した16進数エスケープをデコードします
}
```

<!-- Another option is to use the byte array/slice data type in your JSON object, but the binary data will have to be base64 encoded. -->

別の選択肢として、JSONオブジェクトにバイト配列/スライスのデータ型を使用することもできますが、バイナリデータはbase64エンコードされている必要があります。

```go
package main

import (
  "fmt"
  "encoding/json"
)

type config struct {
  Data []byte `json:"data"`
}

func main() {
  raw := []byte(`{"data":"wg=="}`)
  var decoded config
  
  if err := json.Unmarshal(raw, &decoded); err != nil {
          fmt.Println(err)
      }
  
  fmt.Printf("%#v",decoded) //prints: main.config{Data:[]uint8{0xc2}}
}
```

<!-- Something else to watch out for is the Unicode replacement character (U+FFFD). Go will use the replacement character instead of invalid UTF8, so the Unmarshal/Decode call will not fail, but the string value you get might not be what you expected. -->

その他に気をつけなければならないのは、Unicode置換文字(U+FFFD)です。Goは無効なUTF8の代わりに置換文字を使用するので、Unmarshal/Decodeの呼び出しは失敗しませんが、得られる文字列の値は期待したものとは異なるかもしれません。

### 構造体、配列、スライス、マップの比較

<!-- You can use the equality operator, `==`, to compare struct variables if each structure field can be compared with the equality operator. -->

構造体の変数を比較する場合、それぞれの構造体のフィールドが等価演算子で比較可能な場合は等価演算子 `==` を使用することができます。

```go
package main

import "fmt"

type data struct {  
    num int
    fp float32
    complex complex64
    str string
    char rune
    yes bool
    events <-chan string
    handler interface{}
    ref *byte
    raw [10]byte
}

func main() {  
    v1 := data{}
    v2 := data{}
    fmt.Println("v1 == v2:",v1 == v2) //prints: v1 == v2: true
}
```

<!-- If any of the struct fields are not comparable then using the equality operator will result in compile time errors. Note that arrays are comparable only if their data items are comparable. -->

構造体のフィールドのいずれかが等価演算子を用いて比較できない場合は、等価演算子を使用するとコンパイル時にエラーが発生します。配列が比較可能であるのは、配列のデータ項目が比較可能である場合のみであることに注意してください。

```go
package main

import "fmt"

type data struct {  
    num int                //ok
    checks [10]func() bool //比較できません
    doit func() bool       //比較できません
    m map[string] string   //比較できません
    bytes []byte           //比較できません
}

func main() {  
    v1 := data{}
    v2 := data{}
    fmt.Println("v1 == v2:",v1 == v2)
}
```

<!-- Go does provide a number of helper functions to compare variables that can't be compared using the comparison operators. -->

Goは等価演算子を用いて比較できない変数を比較可能するためにいくつかのヘルパー関数を提供しています。

<!-- The most generic solution is to use the `DeepEqual()` function in the reflect package. -->

最も一般的な方法は reflect パッケージにある `DeepEqual()` を使うことです。

```go
package main

import (  
    "fmt"
    "reflect"
)

type data struct {  
    num int                //ok
    checks [10]func() bool //比較できません
    doit func() bool       //比較できません
    m map[string] string   //比較できません
    bytes []byte           //比較できません
}

func main() {  
    v1 := data{}
    v2 := data{}
    fmt.Println("v1 == v2:",reflect.DeepEqual(v1,v2)) //prints: v1 == v2: true

    m1 := map[string]string{"one": "a","two": "b"}
    m2 := map[string]string{"two": "b", "one": "a"}
    fmt.Println("m1 == m2:",reflect.DeepEqual(m1, m2)) //prints: m1 == m2: true

    s1 := []int{1, 2, 3}
    s2 := []int{1, 2, 3}
    fmt.Println("s1 == s2:",reflect.DeepEqual(s1, s2)) //prints: s1 == s2: true
}
```

<!-- Aside from being slow (which may or may not be a deal breaker for your application), `DeepEqual()` also has its own gotchas. -->

しかし `DeepEqual()` が(アプリケーションにとって問題かどうかにかかわらず)遅いことは別にして、それ自体に問題点もあります。

```go
package main

import (  
    "fmt"
    "reflect"
)

func main() {  
    var b1 []byte = nil
    b2 := []byte{}
    fmt.Println("b1 == b2:",reflect.DeepEqual(b1, b2)) //prints: b1 == b2: false
}
```

<!-- `DeepEqual()` doesn't consider an empty slice to be equal to a "nil" slice. This behavior is different from the behavior you get using the `bytes.Equal()` function. `bytes.Equal()` considers "nil" and empty slices to be equal. -->

`DeepEqual()` は空のスライスが "nil" スライスと等価であるとみなしません。`bytes.Equal()` 関数を使って得られる動作とは異なります。`bytes.Equal()` は "nil" スライスと空スライスは等価であるとみなします。

```go
package main

import (  
    "fmt"
    "bytes"
)

func main() {  
    var b1 []byte = nil
    b2 := []byte{}
    fmt.Println("b1 == b2:",bytes.Equal(b1, b2)) //prints: b1 == b2: true
}
```

<!-- `DeepEqual()` isn't always perfect comparing slices. -->

また `DeepEqual()` はスライスの比較を常に完璧に行うとは限りません。

```go
package main

import (  
    "fmt"
    "reflect"
    "encoding/json"
)

func main() {  
    var str string = "one"
    var in interface{} = "one"
    fmt.Println("str == in:",str == in,reflect.DeepEqual(str, in)) 
    //prints: str == in: true true

    v1 := []string{"one","two"}
    v2 := []interface{}{"one","two"}
    fmt.Println("v1 == v2:",reflect.DeepEqual(v1, v2)) 
    //prints: v1 == v2: false (okではありません)

    data := map[string]interface{}{
        "code": 200,
        "value": []string{"one","two"},
    }
    encoded, _ := json.Marshal(data)
    var decoded map[string]interface{}
    json.Unmarshal(encoded, &decoded)
    fmt.Println("data == decoded:",reflect.DeepEqual(data, decoded)) 
    //prints: data == decoded: false (okではありません)
}
```

<!-- If your byte slices (or strings) contain text data you might be tempted to use `ToUpper()` or `ToLower()` from the "bytes" and "strings" packages when you need to compare values in a case insensitive manner (before using `==`,`bytes.Equal()`, or `bytes.Compare()`). It will work for English text, but it will not work for text in many other languages. `strings.EqualFold()` and `bytes.EqualFold()` should be used instead. -->

バイトスライス(や文字列)がテキストデータを含んでいる場合で、大文字小文字を区別せずに値を比較する必要があるとき、(`==` や `bytes.Equal()`、`bytes.Compare()` を使う前に)"bytes" パッケージや "strings" パッケージの `ToUpper()` や `ToLower()` 関数を使いたくなるかもしれません。英語のテキストでは機能しますが、他の言語の場合は機能しません。`strings.EqualFold()` や `bytes.EqualFold()` を代わりに使うべきです。

<!-- If your byte slices contain secrets (e.g., cryptographic hashes, tokens, etc.) that need to be validated against user-provided data, don't use `reflect.DeepEqual()`, `bytes.Equal()`, or `bytes.Compare()` because those functions will make your application vulnerable to **timing attacks**. To avoid leaking the timing information use the functions from the 'crypto/subtle' package (e.g., `subtle.ConstantTimeCompare()`). -->

バイトスライスに(暗号化ハッシュ、トークンといった)シークレットが含まれており、ユーザが提供したデータに対して照合する必要があるときは `reflect.DeepEqual()` や `bytes.Equal()`、`bytes.Compare()` を使わないでください。アプリケーションが [**タイミング攻撃**](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%82%A4%E3%83%9F%E3%83%B3%E3%82%B0%E6%94%BB%E6%92%83) に対して脆弱になるためです。タイミング情報の漏洩を避けるには、"crypto/subtle" パッケージの関数を使用してください(例: `subtle.ConstantTimeCompare()` など)。

### panicの回復

<!-- The `recover()` function can be used to catch/intercept a panic. Calling `recover()` will do the trick only when it's done in a deferred function. -->

panicをキャッチ/インターセプトするために `recover()` 関数が使われます。`recover()` の呼び出しは、遅延関数の中で行われた場合のみ、呼び出されます。

<!-- Incorrect: -->
誤り:

```go
package main

import "fmt"

func main() {  
    recover() //何もしません
    panic("not good")
    recover() //実行されません
    fmt.Println("ok")
}
```

<!-- Works: -->
修正後:

```go
package main

import "fmt"

func main() {  
    defer func() {
        fmt.Println("recovered:",recover())
    }()

    panic("not good")
}
```

<!-- The call to `recover()` works only if it's called directly in your deferred function. -->

`recover()` の呼び出しは、遅延関数の中で直接呼び出された場合にのみ動作します。

<!-- Fails: -->
失敗例:

```go
package main

import "fmt"

func doRecover() {  
    fmt.Println("recovered =>",recover()) //prints: recovered => <nil>
}

func main() {  
    defer func() {
        doRecover() //panicは回復されません
    }()

    panic("not good")
}
```

### スライス、配列、マップの"for-range"句での項目の更新と参照

<!-- The data values generated in the "range" clause are copies of the actual collection elements. They are not references to the original items. This means that updating the values will not change the original data. It also means that taking the address of the values will not give you pointers to the original data. -->

"range" 句の中で生成されたデータ値は、実際のコレクション要素のコピーです。元の項目を参照しているわけではありません。つまり値を更新しても元のデータは変更されません。同様に、値のアドレスを取得しても元のデータへのポインタは与えられていません。

```go
package main

import "fmt"

func main() {  
    data := []int{1,2,3}
    for _,v := range data {
        v *= 10 //元の項目は変更されていません。
    }

    fmt.Println("data:",data) //prints data: [1 2 3]
}
```

<!-- If you need to update the original collection record value use the index operator to access the data. -->

元のコレクションレコードの値を更新する必要がある場合は、インデックス演算子を使用してデータにアクセスします。

```go
package main

import "fmt"

func main() {  
    data := []int{1,2,3}
    for i,_ := range data {
        data[i] *= 10
    }

    fmt.Println("data:",data) //prints data: [10 20 30]
}
```

<!-- If your collection holds pointer values then the rules are slightly different. You still need to use the index operator if you want the original record to point to another value, but you can update the data stored at the target location using the second value in the "for range" clause. -->

コレクションがポインタ値を保持している場合、ルールは少し異なります。元のレコードが別の値を指すようにしたい場合は引き続きインデックス演算子を使う必要がありますが、ターゲットの場所が格納されている値を更新したい場合は、"for range" 句で取得できる2番目の値を使って更新できます。

```go
package main

import "fmt"

func main() {  
    data := []*struct{num int} {{1},{2},{3}}

    for _,v := range data {
        v.num *= 10
    }

    fmt.Println(data[0],data[1],data[2]) //prints &{10} &{20} &{30}
}
```

### スライスの"隠れた"データ

<!-- When you reslice a slice, the new slice will reference the array of the original slice. If you forget about this behavior it can lead to unexpected memory usage if your application allocates large temporary slices creating new slices from them to refer to small sections of the original data. -->

スライスから再スライスすると、新しいスライスは元のスライスの配列を参照します。この動作を忘れると、アプリケーションが一時的に大きなスライスを新規に生成して、そこから元のデータの小さな一部を参照する場合に、予期せぬメモリ使用量になる場合があります。

```go
package main

import "fmt"

func get() []byte {  
    raw := make([]byte,10000)
    fmt.Println(len(raw),cap(raw),&raw[0]) //prints: 10000 10000 <byte_addr_x>
    return raw[:3]
}

func main() {  
    data := get()
    fmt.Println(len(data),cap(data),&data[0]) //prints: 3 10000 <byte_addr_x>
}
```

<!-- To avoid this trap make sure to copy the data you need from the temporary slice (instead of reslicing it). -->

この罠を避けるためには、(再スライスする代わりに)一時的に作成したスライスから必要なデータをコピーするようにしてください。

```go
package main

import "fmt"

func get() []byte {  
    raw := make([]byte,10000)
    fmt.Println(len(raw),cap(raw),&raw[0]) //prints: 10000 10000 <byte_addr_x>
    res := make([]byte,3)
    copy(res,raw[:3])
    return res
}

func main() {  
    data := get()
    fmt.Println(len(data),cap(data),&data[0]) //prints: 3 3 <byte_addr_y>
}
```

### スライスデータの"破損"

<!-- Let's say you need to rewrite a path (stored in a slice). You reslice the path to reference each directory modifying the first folder name and then you combine the names to create a new path. -->

(スライスに格納されている)パスを書き換える必要があるとしましょう。それぞれのディレクトリを参照するようにパスを再スライスし、最初のフォルダ名を変更します。そして、新しいパスを生成するためにそれぞれのディレクトリ名を組み合わせます。

```go
package main

import (  
    "fmt"
    "bytes"
)

func main() {  
    path := []byte("AAAA/BBBBBBBBB")
    sepIndex := bytes.IndexByte(path,'/')
    dir1 := path[:sepIndex]
    dir2 := path[sepIndex+1:]
    fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAA
    fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB

    dir1 = append(dir1,"suffix"...)
    path = bytes.Join([][]byte{dir1,dir2},[]byte{'/'})

    fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAAsuffix
    fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => uffixBBBB (okではありません)

    fmt.Println("new path =>",string(path))
}
```

<!-- It didn't work as you expected. Instead of "AAAAsuffix/BBBBBBBBB" you ended up with "AAAAsuffix/uffixBBBB". It happened because both directory slices referenced the same underlying array data from the original path slice. This means that the original path is also modified. Depending on your application this might be a problem too. -->

期待通りには動きませんでした。"AAAAsuffix/BBBBBBBBB"の代わりに"AAAAsuffix/uffixBBBB"になってしまいました。これは両方のディレクトリのスライスが、元のパスのスライスから同じ背後にある配列データを参照していたために起こりました。つまり元のパスも変更されています。アプリケーションによっては、これも問題になるかもしれません。

<!-- This problem can fixed by allocating new slices and copying the data you need. Another option is to use the full slice expression. -->

この問題は新しいスライスを割り当てて、必要なデータをコピーすることで解決できます。もう一つの選択肢は、フルスライス式を使用することです。

```go
package main

import (  
    "fmt"
    "bytes"
)

func main() {  
    path := []byte("AAAA/BBBBBBBBB")
    sepIndex := bytes.IndexByte(path,'/')
    dir1 := path[:sepIndex:sepIndex] //フルスライス式
    dir2 := path[sepIndex+1:]
    fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAA
    fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB

    dir1 = append(dir1,"suffix"...)
    path = bytes.Join([][]byte{dir1,dir2},[]byte{'/'})

    fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAAsuffix
    fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB (ok now)

    fmt.Println("new path =>",string(path))
}
```

<!-- The extra parameter in the full slice expression controls the capacity for the new slice. Now appending to that slice will trigger a new buffer allocation instead of overwriting the data in the second slice. -->

フルスライス式の追加パラメータは、新しいスライスの容量を制御します。これにより、そのスライスに値を追加すると、2つ目のスライスのデータを上書きする代わりに、新しいバッファを割り当てるようになります。

### "古く"なるスライス

<!-- Multiple slices can reference the same data. This can happen when you create a new slice from an existing slice, for example. If your application relies on this behavior to function properly then you'll need to worry about "stale"slice. -->

複数のスライスは同じデータを参照できます。これは例えば既存のスライスから新しいスライスを生成する場合に起こります。この動作に依存するアプリケーションが適切に機能するためには、"古く"なるスライスを気にする必要があります。

<!-- At some point adding data to one of the slices will result in a new array allocation when the original array can't hold any more new data. Now other slices will point to the old array (with old data). -->

元の配列が新しいデータを保持できないときにスライスにデータを追加すると、新しい配列が割り当てられます。このとき、元のスライスを参照している他のスライスは(古いデータがある)古い配列を指すようになります。

```go
import "fmt"

func main() {  
    s1 := []int{1,2,3}
    fmt.Println(len(s1),cap(s1),s1) //prints 3 3 [1 2 3]

    s2 := s1[1:]
    fmt.Println(len(s2),cap(s2),s2) //prints 2 2 [2 3]

    for i := range s2 { s2[i] += 20 }

    //まだ同じ配列を参照しています
    fmt.Println(s1) //prints [1 22 23]
    fmt.Println(s2) //prints [22 23]

    s2 = append(s2,4)

    for i := range s2 { s2[i] += 10 }

    //ここではs1は"古く"なっています
    fmt.Println(s1) //prints [1 22 23]
    fmt.Println(s2) //prints [32 33 14]
}
```

### 型宣言とメソッド

<!-- When you create a type declaration by defining a new type from an existing (non-interface) type, you don't inherit the methods defined for that existing type. -->

既存の(非インターフェースの)型から新しい型を定義して型宣言するとき、既存の型に定義されているメソッドは継承されません。

<!-- Fails: -->
失敗例:

```go
package main

import "sync"

type myMutex sync.Mutex

func main() {  
    var mtx myMutex
    mtx.Lock() //エラー
    mtx.Unlock() //エラー  
}
```

<!-- Compile Errors: -->
コンパイルエラー:

> /tmp/sandbox106401185/main.go:9: mtx.Lock undefined (type myMutex has no field or method Lock) /tmp/sandbox106401185/main.go:10: mtx.Unlock undefined (type myMutex has no field or method Unlock)

<!-- If you do need the methods from the original type you can define a new struct type embedding the original type as an anonymous field. -->

元の型のメソッドを必要とする場合、元の型を匿名フィールドとして埋め込んで、新しい struct 型を定義することができます。

<!-- Works: -->
修正後:

```go
package main

import "sync"

type myLocker struct {  
    sync.Mutex
}

func main() {  
    var lock myLocker
    lock.Lock() //ok
    lock.Unlock() //ok
}
```

<!-- Interface type declarations also retain their method sets. -->

インターフェース型宣言でも同様にメソッドセットを保持します。

<!-- Works: -->
修正後:

```go
package main

import "sync"

type myLocker sync.Locker

func main() {  
    var lock myLocker = new(sync.Mutex)
    lock.Lock() //ok
    lock.Unlock() //ok
}
```

### "for-switch"や"for-select"のコードブロックにおけるbreak

<!-- A "break" statement without a label only gets you out of the inner switch/select block. If using a "return" statement is not an option then defining a label for the outer loop is the next best thing. -->

ラベルがない "break" ステートメントは内部のswitchやselectブロックから抜けるだけです。"return"ステートメントが使えない場合、ループの外でラベルを定義することが次善の策です。

```go
package main

import "fmt"

func main() {  
    loop:
        for {
            switch {
            case true:
                fmt.Println("breaking out...")
                break loop
            }
        }

    fmt.Println("out!")
}
```

<!-- A "goto" statement will do the trick too... -->

"goto" ステートメントも上記のように動きます...

### "for"文の中のイテレーション変数とクロージャ

<!-- This is the most common gotcha in Go. The iteration variables in `for` statements are reused in each iteration. This means that each closure (aka function literal) created in your `for` loop will reference the same variable (and they'll get that variable's value at the time those goroutines start executing). -->

これはとてもよくあるGoの落とし穴です。`for` ステートメントのイテレーション変数はそれぞれのイテレーションで再利用されます。つまり `for` ループ内のクロージャは同じ変数を参照しているということです(そしてgoroutineは実行され始めた時点でその変数の値を取得します)。

<!-- Incorrect: -->
誤り:

```go
package main

import (  
    "fmt"
    "time"
)

func main() {  
    data := []string{"one","two","three"}

    for _,v := range data {
        go func() {
            fmt.Println(v)
        }()
    }

    time.Sleep(3 * time.Second)
    //goroutines print: three, three, three
}
```

<!-- The easiest solution (that doesn't require any changes to the goroutine) is to save the current iteration variable value in a local variable inside the `for` loop block. -->

(goroutineに対して変更がいらない)最も簡単な解決策は `for` ループのブロック内でローカル変数として現在のイテレーション変数の値を保存することです。

<!-- Works: -->
修正後:

```go
package main

import (  
    "fmt"
    "time"
)

func main() {  
    data := []string{"one","two","three"}

    for _,v := range data {
        vcopy := v //
        go func() {
            fmt.Println(vcopy)
        }()
    }

    time.Sleep(3 * time.Second)
    //goroutines print: one, two, three
}
```

<!-- Another solution is to pass the current iteration variable as a parameter to the anonymous goroutine. -->

別の解決策はパラメータとして現在のイテレーション変数を匿名のgoroutineに渡すことです。

<!-- Works: -->
修正後:

```go
package main

import (  
    "fmt"
    "time"
)

func main() {  
    data := []string{"one","two","three"}

    for _,v := range data {
        go func(in string) {
            fmt.Println(in)
        }(v)
    }

    time.Sleep(3 * time.Second)
    //goroutines print: one, two, three
}
```

<!-- Here's a slightly more complicated version of the trap. -->

もう少し複雑な罠を紹介します。

<!-- Incorrect: -->
誤り:

```go
package main

import (  
    "fmt"
    "time"
)

type field struct {  
    name string
}

func (p *field) print() {  
    fmt.Println(p.name)
}

func main() {  
    data := []field{{"one"},{"two"},{"three"}}

    for _,v := range data {
        go v.print()
    }

    time.Sleep(3 * time.Second)
    //goroutines print: three, three, three
}
```

<!-- Works: -->
修正後:

```go
package main

import (  
    "fmt"
    "time"
)

type field struct {  
    name string
}

func (p *field) print() {  
    fmt.Println(p.name)
}

func main() {  
    data := []field{{"one"},{"two"},{"three"}}

    for _,v := range data {
        v := v
        go v.print()
    }

    time.Sleep(3 * time.Second)
    //goroutines print: one, two, three
}
```

<!-- What do you think you'll see when you run this code (and why)? -->
このコードを実行すると何が表示されるか(理由も含めて)考えてみてください。

```go
package main

import (  
    "fmt"
    "time"
)

type field struct {  
    name string
}

func (p *field) print() {  
    fmt.Println(p.name)
}

func main() {  
    data := []*field{{"one"},{"two"},{"three"}}

    for _,v := range data {
        go v.print()
    }

    time.Sleep(3 * time.Second)
}
```

### 遅延関数呼び出しの引数評価

<!-- Arguments for a deferred function call are evaluated when the `defer` statement is evaluated (not when the function is actually executing). The same rules apply when you defer a method call. The structure value is also saved along with the explicit method parameters and the closed variables. -->

遅延関数呼び出しの引数は `defer` ステートメントが評価されたときに評価されます(関数が実際に実行されるときではありません)。メソッド呼び出しを遅延する場合も、同様のルールが適用されます。構造体の値は明示的なメソッドのパラメータに加えて、非公開の変数も一緒に保存されます。

```go
package main

import "fmt"

func main() {  
    var i int = 1

    defer fmt.Println("result =>",func() int { return i * 2 }())
    i++
    //prints: result => 2 (4を期待している場合は問題です)
}
```

<!-- If you have pointer parameters it is possible to change the values they point to because only the pointer is saved when the `defer` statement is evaluated. -->

ポインタのパラメータの場合、`defer` ステートメントが評価されたときにポインタのみが保存されるため、ポインタが示す値を変更することができます。

```go
package main

import (
  "fmt"
)

func main() {
  i := 1
  defer func (in *int) { fmt.Println("result =>", *in) }(&i)
  
  i = 2
  //prints: result => 2
}
```

### 遅延関数呼び出しの実行

<!-- The deferred calls are executed at the end of the containing function (and in reverse order) and not at the end of the containing code block. It's an easy mistake to make for new Go developers confusing the deferred code execution rules with the variable scoping rules. It can become a problem if you have a long running function with a for loop that tries to defer resource cleanup calls in each iteration. -->

遅延呼び出しは格納されている関数の最後で実行されます(逆の順番で)。格納されているコードブロックの最後で実行されるわけではありません。新米Gopherが犯しやすい誤りとして、遅延呼び出しコードの実行ルールと変数スコープのルールを混同することがあります。これは長く実行される関数において、forループ内の各イテレーションでリソースのクリーンアップを遅延呼び出しで実行しようとする場合に、問題になる可能性があります。

```go
package main

import (  
    "fmt"
    "os"
    "path/filepath"
)

func main() {  
    if len(os.Args) != 2 {
        os.Exit(-1)
    }

    start, err := os.Stat(os.Args[1])
    if err != nil || !start.IsDir(){
        os.Exit(-1)
    }

    var targets []string
    filepath.Walk(os.Args[1], func(fpath string, fi os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if !fi.Mode().IsRegular() {
            return nil
        }

        targets = append(targets,fpath)
        return nil
    })

    for _,target := range targets {
        f, err := os.Open(target)
        if err != nil {
            fmt.Println("bad target:",target,"error:",err) //prints error: too many open files
            break
        }
        defer f.Close() //このコードブロックの最後では閉じられません。
        //ファイルを使った何かの処理...
    }
}
```

<!-- One way to solve the problem is by wrapping the code block in a function. -->

この問題を解決する一つの方法は、コードブロックを関数でラップすることです。

```go
package main

import (  
    "fmt"
    "os"
    "path/filepath"
)

func main() {  
    if len(os.Args) != 2 {
        os.Exit(-1)
    }

    start, err := os.Stat(os.Args[1])
    if err != nil || !start.IsDir(){
        os.Exit(-1)
    }

    var targets []string
    filepath.Walk(os.Args[1], func(fpath string, fi os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if !fi.Mode().IsRegular() {
            return nil
        }

        targets = append(targets,fpath)
        return nil
    })

    for _,target := range targets {
        func() {
            f, err := os.Open(target)
            if err != nil {
                fmt.Println("bad target:",target,"error:",err)
                return
            }
            defer f.Close() //ok
            //ファイルを使った何かの処理...
        }()
    }
}
```

<!-- Another option is to get rid of the `defer` statement :-) -->

もう一つの方法は `defer` ステートメントをなくすことです。

### 型アサーションの失敗

<!-- 型アサーションの失敗 return the "zero value" for the target type used in the assertion statement. This can lead to unexpected behavior when it's mixed with variable shadowing. -->

型アサーションに失敗すると、アサーションのステートメントが使われている対象の型の"ゼロ値"がリターンされます。変数のシャドーイングが混ざっている場合に、予期せぬ動作になる可能性があります。

誤り:

```go
package main

import "fmt"

func main() {  
    var data interface{} = "great"

    if data, ok := data.(int); ok {
        fmt.Println("[is an int] value =>",data)
    } else {
        fmt.Println("[not an int] value =>",data) 
        //prints: [not an int] value => 0 ("great" ではありません)
    }
}
```

修正後:

```go
package main

import "fmt"

func main() {  
    var data interface{} = "great"

    if res, ok := data.(int); ok {
        fmt.Println("[is an int] value =>",res)
    } else {
        fmt.Println("[not an int] value =>",data) 
        //prints: [not an int] value => great (期待したとおりです)
    }
}
```

### ブロックされるgoroutineとリソースリーク

<!-- Rob Pike talked about a number of fundamental concurrency patterns in his "Go Concurrency Patterns" presentation at Google I/O in 2012. Fetching the first result from a number of targets is one of them. -->

Rob Pike氏は2012年にあったGoogle I/Oで行われた "Go Concurrency Patterns" のプレゼンテーションの中で、いくつかの基本的な並行処理のパターンの話をしました。複数のターゲットから最初の結果を取得する話もその一つです。

```go
func First(query string, replicas ...Search) Result {  
    c := make(chan Result)
    searchReplica := func(i int) { c <- replicas[i](query) }
    for i := range replicas {
        go searchReplica(i)
    }
    return <-c
}
```

<!-- The function starts a goroutines for each search replica. Each goroutine sends its search result to the result channel. The first value from the result channel is returned. -->

上記の関数はそれぞれの検索レプリカに対してgoroutineを開始します。それぞれのgoroutineはresultチャネルに検索結果を送信します。resultチャネルからは最初に送信された値が返ってきます。

<!-- What about the results from the other goroutines? What about the goroutines themselves? -->
その他のgoroutineからの結果はどうなるでしょうか？goroutine自体はどうなりますか？

<!-- The result channel in the `First()` function is unbuffered. This means that only the first goroutine returns. All other goroutines are stuck trying to send their results. This means if you have more than one replica each call will leak resources. -->

`First()` 関数の中にあるresultチャネルはバッファがありません。つまり最初のgoroutineだけが結果を返します。その他のgoroutineは結果を送信しようとしてスタックします。検索レプリカが1よりも多い場合、その他のレプリカの呼び出しによってリソースがリークします。

<!-- To avoid the leaks you need to make sure all goroutines exit. One potential solution is to use a buffered result channel big enough to hold all results. -->

リークを避けるためには、すべてのgoroutineが必ず終了するようにする必要があります。考えられる解決策の一つはすべての結果を保持できる十分な大きさがあるバッファ付きのresultチャネルを使うことです。

```go
func First(query string, replicas ...Search) Result {  
    c := make(chan Result,len(replicas))
    searchReplica := func(i int) { c <- replicas[i](query) }
    for i := range replicas {
        go searchReplica(i)
    }
    return <-c
}
```

<!-- Another potential solution is to use a `select` statement with a `default` case and a buffered result channel that can hold one value. The `default` case ensures that the goroutines don't get stuck even when the result channel can't receive messages. -->

その他の解決先は `default` 句がある `select` ステートメントと1つの値を保持できるバッファ付きのresultチャネルを使うことです。`default` 句はresultチャネルがメッセージを受信できない場合においてもgoroutineがスタックしないことを保証します。

```go
func First(query string, replicas ...Search) Result {  
    c := make(chan Result,1)
    searchReplica := func(i int) { 
        select {
        case c <- replicas[i](query):
        default:
        }
    }
    for i := range replicas {
        go searchReplica(i)
    }
    return <-c
}
```

<!-- You can also use a special cancellation channel to interrupt the workers. -->
またワーカーを中断するためにキャンセル専用のチャネルを使うことができます。

```go
func First(query string, replicas ...Search) Result {  
    c := make(chan Result)
    done := make(chan struct{})
    defer close(done)
    searchReplica := func(i int) { 
        select {
        case c <- replicas[i](query):
        case <- done:
        }
    }
    for i := range replicas {
        go searchReplica(i)
    }

    return <-c
}
```

<!-- Why did the presentation contain these bugs? Rob Pike simply didn't want to comlicate the slides. It makes sense, but it can be a problem for new Go developers who would use the code as is without thinking that it might have problems. -->

なぜプレゼンテーションではこれらのバグを含んでいたのでしょうか？Rob Pike氏は単にスライドを複雑にしたくなかっただけです。これは理にかなっていますが、問題があるかもしれないと考えずにこのコードを使ってしまうような新米Gopherにとっては問題になる可能性があります。

### 異なるサイズ0の変数が同じアドレスになる

<!-- If you have two different variables shouldn't they have different addresses? Well, it's not the case with Go :-) If you have zero-sized variables they might share the exact same address in memory. -->

2つの異なる変数がある場合に、それらのアドレスは異なるのでしょうか？Goではそうでない場合もあります。変数のサイズが0の場合、メモリ上は全く同じアドレスを共有しているかもしれません。

```go
package main

import (
  "fmt"
)

type data struct {
}

func main() {
  a := &data{}
  b := &data{}
  
  if a == b {
    fmt.Printf("same address - a=%p b=%p\n",a,b)
    //prints: same address - a=0x1953e4 b=0x1953e4
  }
}
```

### iotaの始まりが常に0になるわけではない

<!-- It may seem like the `iota` identifyer is like an increment operator. You start a new constant declaration and the first time you use `iota` you get zero, the second time you use it you get one and so on. It's not always the case though. -->

`iota` 識別子はインクリメント演算子のようなものだと思うかもしれません。新しい定数を宣言して `iota` を使うと、最初は0が得られ、2回目に使うと1が得られる、といったものです。しかし必ずしもそうとは限りません。

```go
package main

import (
  "fmt"
)

const (
  azero = iota
  aone  = iota
)

const (
  info  = "processing"
  bzero = iota
  bone  = iota
)

func main() {
  fmt.Println(azero,aone) //prints: 0 1
  fmt.Println(bzero,bone) //prints: 1 2
}
```

<!-- The `iota` is really an index operator for the current line in the constant declaration block, so if the first use of `iota` is not the first line in the constant declaration block the initial value will not be zero. -->

`iota` は実際には定数宣言のブロックに対して現在の行へのインデックス演算子なので、`iota` を最初に使うときに、定数宣言ブロックの最初の行でない場合は、初期値は0ではありません。