Code Fix

中級

appendの戻り値を再代入し忘れると要素が反映されない

appendは新しいスライスを返す関数で、元のスライス変数を直接書き換えません。戻り値を元の変数に代入し直さないと、追加した要素が失われます。

なぜエラーが出ないのか

出力: [1 2 3]
(エラーなし)
Goは何も報告しません。コンパイルも実行も正常に終わるコードだからです
出力: [1 2 3]
実際の出力 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  package main
 2  
 3  import "fmt"
 4  
 5  func addOne(nums []int) []int {
 6  	_ = append(nums, 4)   
                ^
 7  	return nums
 8  }
 9  
10  func main() {
11  	nums := []int{1, 2, 3}
12  	result := addOne(nums)
13  	fmt.Println(result)
14  }
出力: [1 2 3]

appendは新しいスライスを返すだけで、元のnumsを直接書き換えません。戻り値を代入し直さないと追加した要素が失われます。

直し方: _ = append(nums, 4)nums = append(nums, 4) にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  package main
 2  
 3  import "fmt"
 4  
 5  func addOne(nums []int) []int {
 6  	_ = append(nums, 30)   
                ^
 7  	return nums
 8  }
 9  
10  func main() {
11  	nums := []int{10, 20}
12  	result := addOne(nums)
13  	fmt.Println(result)
14  }
出力: [10 20]

appendの戻り値を捨ててしまうと、容量が足りず新しい配列が確保された場合は変更が一切反映されません。

直し方: _ = append(nums, 30)nums = append(nums, 30) にします。

この問題を解いてみる →

パターン3

 1  package main
 2  
 3  import "fmt"
 4  
 5  func addOne(nums []int) []int {
 6  	_ = append(nums, 6)   
                ^
 7  	return nums
 8  }
 9  
10  func main() {
11  	nums := []int{5}
12  	result := addOne(nums)
13  	fmt.Println(result)
14  }
出力: [5]

要素を1つ追加したつもりでも、戻り値を受け取っていなければreturnされるのは元のnumsのままです。

直し方: _ = append(nums, 6)nums = append(nums, 6) にします。

この問題を解いてみる →

パターン4

 1  package main
 2  
 3  import "fmt"
 4  
 5  func addOne(nums []int) []int {
 6  	_ = append(nums, 11)   
                ^
 7  	return nums
 8  }
 9  
10  func main() {
11  	nums := []int{7, 8, 9, 10}
12  	result := addOne(nums)
13  	fmt.Println(result)
14  }
出力: [7 8 9 10]

append単体の呼び出しは戻り値を使わない式文としては許されず、_に代入するなどして明示的に捨てる必要があります。その結果、変更はnumsに反映されないまま捨てられてしまいます。

直し方: _ = append(nums, 11)nums = append(nums, 11) にします。

この問題を解いてみる →

パターン5

 1  package main
 2  
 3  import "fmt"
 4  
 5  func addOne(nums []int) []int {
 6  	_ = append(nums, 1)   
                ^
 7  	return nums
 8  }
 9  
10  func main() {
11  	nums := []int{0}
12  	result := addOne(nums)
13  	fmt.Println(result)
14  }
出力: [0]

appendの結果を必ず何らかの変数に代入する、という原則を忘れると起きる典型的なバグです。

直し方: _ = append(nums, 1)nums = append(nums, 1) にします。

この問題を解いてみる →

よくある誤解

「appendはスライスの中身を直接書き換えるはず」という思い込みは誤りです。容量が足りない場合appendは新しい配列を確保するため、常に戻り値を元の変数へ代入し直す必要があります。

まとめ

appendの戻り値を再代入し忘れると要素が反映されないは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)