slice bounds out of range の原因と直し方
スライスをs[a:b]の形で切り出す際、範囲の終端が容量を超えているとパニックします。境界の指定はスライスの長さや容量を超えないことが前提です。
エラーメッセージの読み方
panic: runtime error: slice bounds out of range [:10] with capacity 3
panic- パニック — 実行時に回復不能な状態になったことを示します。deferとrecoverで捕まえない限り、そのままプロセスが終了します
runtime error: slice bounds out of range [:10] with capacity 3- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 package main 2 3 import "fmt" 4 5 func main() { 6 nums := []int{1, 2, 3} 7 fmt.Println(nums[1:10]) ^ 8 }
panic: runtime error: slice bounds out of range [:10] with capacity 3capacity 3
numsの容量は3なので、終端に指定できるのは3までです。10は容量を超えています。
直し方: 10 を 3 にします。
広告
広告スロット(未設定)
パターン2
1 package main 2 3 import "fmt" 4 5 func main() { 6 nums := []int{1, 2} 7 fmt.Println(nums[1:5 ]) ^ 8 }
panic: runtime error: slice bounds out of range [:5] with capacity 2capacity 2
容量2のスライスに対して終端5を指定しています。存在する分だけに丸められることはありません。
直し方: 5 を 2 にします。
パターン3
1 package main 2 3 import "fmt" 4 5 func main() { 6 nums := []int{1, 2, 3, 4, 5} 7 fmt.Println(nums[1:8 ]) ^ 8 }
panic: runtime error: slice bounds out of range [:8] with capacity 5capacity 5
容量5のスライスの終端に8を指定するとパニックします。有効な範囲は0〜5です。
直し方: 8 を 5 にします。
パターン4
1 package main 2 3 import "fmt" 4 5 func main() { 6 nums := []int{9, 8, 7} 7 fmt.Println(nums[1:6 ]) ^ 8 }
panic: runtime error: slice bounds out of range [:6] with capacity 3capacity 3
終端が容量を超えているかどうかは実行時にしか判定できないため、コンパイルは通ってしまいます。
直し方: 6 を 3 にします。
パターン5
1 package main 2 3 import "fmt" 4 5 func main() { 6 nums := []int{0, 1, 2, 3} 7 fmt.Println(nums[1:9 ]) ^ 8 }
panic: runtime error: slice bounds out of range [:9] with capacity 4capacity 4
境界の指定はスライスの容量を超えないことが前提です。超えると即座にパニックになります。
直し方: 9 を 4 にします。
よくある誤解
「範囲外を指定しても、存在する分だけ切り取ってくれるはず」という思い込みは誤りです。Goのスライスは指定した範囲が完全に有効でないとパニックし、存在する分だけ返すような寛容な動作はしません。
まとめ
slice bounds out of rangeは初級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。