🍣
go言語を扱うときはrangeに気を付けろ
TL;DR
結論からいうとrange{}の中の一時変数はあくまで一時変数なので、元々の配列には何も入らないことに気をつけてください。
i, u := range users{
u = User{} //uは値渡しであり、元々のusersには何も入らないのでダメ
users[i] = User{} //iにはusersのインデックスが入っているのでそこに代入する
}
僕はこれに気づかず、一時間以上悩んでしまったので気をつけてください。。。
起こってたこと
基本の話ですが、go言語の利便さからチャチャっと書いたコードで一時間くらい悩まされたので記事を書きます。
まず、この様にネストされている二つの構造体があります
type User struct{
id int
profile Profile
}
type Profile struct{
zenn string
}
そして、以下のコードを定義したとします。
func main() {
users := []User{
User{},
User{},
User{},
}
_, u := range users{
u.profile.zenn = "zenn is awesome!"
}
log.Printf("%#v", users)
}
するとどうなるでしょう?
go言語を日頃から扱ってる方は「そりゃだめだろ!」というと思いますが、、、
usersのそれぞれのuserの中のprofileには何も入っていません
僕はこれに一時間以上悩みました。なんか動かねえ!!!!!
これの悪いところは見た目では正しいコードに見えるんですよね。おかしそうに見えない。
何がダメなのか
先ほどのコードで、一時変数であるu
に代入しているのが問題ですね。
uは値渡しなので、users{}の値は関係ないです。
よくよく考えたら、phpのforeachや、javaの拡張forなどもそうなのですが、基本foreachはその配列の中の要素全てを一つづつ処理したり、計算にしようしたりと、代入目的ではあまり使わないですよね。
言われてみたらPHPを使ってた時もそんな感じだった!!と思いました。
プログラムの基本文法がなってなかった。。。。
以上です。
Discussion