ぼく 「[]runeを範囲外でスライスしたら当然エラー出るだろうなあ」

ぼく 「あれ？」

```go:Go言語_[]runeのスライス
str := "0123456"
runes := []rune(str)

// 範囲内
fmt.Println(string(runes[0]))   // 0
fmt.Println(string(runes[3]))   // 3
fmt.Println(string(runes[4:6])) // 45
fmt.Println(string(runes[4:7])) // 456

// 範囲外、、のはずだけど
fmt.Println(string(runes[4:8]))   // 456  <=　エラー出ないのか、、
fmt.Println(string(runes[10]))    // エラー： index out of range   <=　わかる
fmt.Println(string(runes[10:20])) // （空文字が出力）
```

ぼく 「範囲外のインデックス指定してるんだから、普通 "xxx out of range" 的なエラーが出るでしょ」
ぼく 「Go言語、まさかスライスで範囲外指定してもいいように察してくれるのか、？」
ぼく 「ここ範囲外だからとりあえず空文字返しとこ、的な」
ぼく 「いやいやいや、、」
ぼく 「stringでやってみよ」

```go:Go言語_string配列のスライス
strArray := []string{"0", "1", "2", "3", "4", "5", "6"}
// 範囲内
fmt.Println(strArray[0])  // 0
fmt.Println(strArray[3])  // 3
fmt.Println(strings.Join(strArray[4:6], ""))  // 45
fmt.Println(strings.Join(strArray[4:7], ""))  // 456

// 範囲外
fmt.Println(strings.Join(strArray[4:8], ""))  // エラー： slice bounds out of range
fmt.Println(strArray[10])  // エラー： index out of range
fmt.Println(strings.Join(strArray[10:20], ""))  // エラー： slice bounds out of range
```

ぼく 「普通にエラー出るな、、」
ぼく 「これならわかる、けどさっきの[]runeの範囲外スライスはなんでエラー出ないんだ」
ぼく 「スライスのスライスだからか、、？　[]runeは確か配列じゃなくてスライスだったな、（※配列の参照、Goには可変長配列がないので代わりにこれをつかう）」
ぼく 「、、stringスライスのスライスならどうだろ」

```go:Go言語_stringスライスのスライス
var strSlice []string
strSlice = append(strSlice, "0", "1", "2", "3", "4", "5", "6")
fmt.Println(strings.Join(strSlice[4:8], ""))  // エラー： slice bounds out of range
fmt.Println(strSlice[10])  // エラー： index out of range
fmt.Println(strings.Join(strSlice[10:20], "")) // エラー： slice bounds out of range
```

ぼく 「変わらないな、、」
ぼく 「スライスのスライスは範囲外でもエラー出ない、とかいう話ではないのか」
ぼく 「なんでruneのスライスだけ、範囲外でスライスしてもエラー出ないんだろう」
ぼく 「（わからんtaskete）」

## 追記(2019/07/31) ： 親切な方(aimofさん)降臨
<img width="801" alt="スクリーンショット 2019-07-31 6.52.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452215/2ad96184-e5e5-f3d3-ae17-668c26574b73.png">

ぼく 「__神は実在した…（激しく感謝）__」
ぼく 「__[aimofさん](https://qiita.com/aimof)__ありがとうございます」
ぼく 「というか__cap__ってなんだ」
ぼく 「キャップだから…__帽子か？__」

調べてみた

* __cap ( capacity ) : 配列の容量__  
 ▲ 要素数(length)とは異なる

ぼく 「Go言語にはlengthだけじゃなくて、capacityとかあるのか…」
ぼく 「で、__[]rune(str)__でキャストするときには、なんか暗黙的にcapacity大きく取られてたってことか」
ぼく 「みてみよ」

```go
str := "0123456"
runes := []rune(str)
fmt.Println(cap([]byte(str)))  // 32
fmt.Println(cap(runes))  // 32

// capacity内
fmt.Println(string(runes[4:32])) // 456

// capacity外
fmt.Println(string(runes[4:33])) // slice bounds out of range
```

ぼく 「ほんとだ、、runeスライスへのキャストで、だいぶ大きめにcapacity取られてるな」
ぼく 「32もある…」
ぼく 「なんでこの数なんだろ」

__（下の方で少し試した（おまけ）ことあります）__


## とりあえずまとめ
 * ~~[]runeは範囲外でスライスしてもいいように察してくれる（エラー出ない）~~
 * ~~それ以外の配列・スライスなら範囲外スライスは普通にエラーがでる~~
 * 配列・スライスの__len, capの問題だった__
 * makeでcapを指定、とかではなく__[]rune(str)__でキャストすると、__capが勝手にある程度の値を取ってくれる__
 * len (=length) : 配列の要素数　（ ◁ わかる ）
 * __cap (=capacity)__ : 配列の__容量__　（ ◁ 知らなかった ）
 * __capの範囲内であれば、例え配列の要素が存在せずとも slice bounds out of range は出ない__

### 補足
 * __string__: 文字列を示すbyteスライスのイミュータブル参照、Go言語ではstr[0]とか書くと1文字目ではなくひとつ目のbyte値が得られる
 * __rune__: Unicodeコードポイント、ざっくりいうと文字１つひとつに割り当てられたコード値. runeのスライスはstringに変換できる


### 追記(2019/07/31) : おまけ
```go
// ▼ 1文字の場合
s := "1"
rs := []rune(s)

// length
fmt.Println(len(rs)) // 1

// capacity　（ <= 1文字でもとりあえず32確保する模様）
fmt.Println(cap([]byte(s))) // 32
fmt.Println(cap(rs))        // 32


// ▼ 32文字の場合
st := "12345678901234567890123456789012"
rus := []rune(st)

// length
fmt.Println(len(rus)) // 32

// capacity　（ <= 32文字なら、まだcapacityも32のまま）
fmt.Println(cap([]byte(st))) // 32
fmt.Println(cap(rus))        // 32


// ▼ 33文字の場合
str := "123456789012345678901234567890123"
runes := []rune(str)

// length
fmt.Println(len(runes)) // 33

// capacity　（ <= 32を超えて初めて増加! ）
fmt.Println(cap([]byte(str))) // 48
fmt.Println(cap(runes))       // 36
```