Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

詳解 "Fixing For Loops in Go 1.22" 自作linterをgolan...

詳解 "Fixing For Loops in Go 1.22" 自作linterをgolangci-lintへコントリビュートした話

Go1.22から(プレビューはGo1.21から)ループ変数のメモリ共有問題が解消されたことは皆様よくご存知かと思います。 cf. Fixing For Loops in Go 1.22

それではもう1歩踏み込んで、ループ変数がイテレーション毎に異なるインスタンスになるのはどのような時でしょうか?以下2つの出力が異なる理由をどう説明できるでしょうか?

for i := range 3 {
fmt.Print(&i) // [0x14000112018, 0x14000112030, 0x14000112038] // 異なるアドレス
}
for i := range 3 {
print(&i) // [0x1400010af18, 0x1400010af18, 0x1400010af18] // 同じアドレス
}

新しいループとそれを取り巻くツールの実装は、既存コードでバグを生み出さない・パフォーマンスを落とさない工夫がされています。

本セッションでは、loopvarパッケージのコードリーディングを通して、これら変更の背後にある内部動作を解説します。 さらに、デザインドキュメントやコミュニティでの議論、周辺ツールを併せて確認することで、セマンティクス変更への理解をより深めたいと思います。

また、Go1.22から不要になったループ変数のコピーを検出する自作linter copyloopvar をgolangci-lintにコントリビュートした話もお伝えします。 このlinterが何をどのように検知するかを紹介する中で、Goにおける静的解析ツールの作成方法も解説します。 linterの自作やOSS貢献に一歩踏み出す際、本セッションがご参考になれば幸いです。

QualiArts

June 07, 2024
Tweet

More Decks by QualiArts

Other Decks in Programming

Transcript

  1. $PNQJMFSͷ͓࢓ࣄͬ͘͟Γ MPPQWBSύοέʔδͷ಺෦࣮૷ΛಡΉ TSDDNEDPNQJMF3&"%.&NE ɾTSDDNEDPNQJMFJOUFSOBMTZOUBY ɾTSDDNEDPNQJMFJOUFSOBMUZQFT ɾTSDDNEDPNQJMFJOUFSOBMJS ɾTSDDNEDPNQJMFJOUFSOBMEFBEDPEF ɾTSDDNEDPNQJMFJOUFSOBMJOMJOF ɾTSDDNEDPNQJMFJOUFSOBMEFWJSUVBMJ[F ɾTSDDNEDPNQJMFJOUFSOBMFTDBQF

    ɾTSDDNEDPNQJMFJOUFSOBMTTB ɾTSDDNEDPNQJMFJOUFSOBMTTBHFO ɾTSDDNEJOUFSOBMPCK தؒදݱ *3 ࡞੒ ɾߏจղੳ ɾܕνΣοΫ ɾதؒදݱ *3 ม׵ ϛουΤϯυ࠷దԽ ɾσουίʔυ࡟আ ɾΠϯϥΠϯԽ ɾԾ૝Խղআ ɾΤεέʔϓղੳ 44"ܗࣜม׵ ɾ੩త୯Ұ୅ೖܗࣜʹม׵ ػցޠม׵ ɾ֤؀ڥͷϚγϯޠʹม׵ ຊ౰͸XBMLͳͲଞ΋৭ʑ΍ͬͯΔ͚Ͳলུ 
  2. $PNQJMFSͷ͓࢓ࣄ(PͰ͸͜͜ʹΞοϓσʔτ͕ೖͬͨ🙆 TSDDNEDPNQJMFJOUFSOBMHDNBJOHP MPPQWBS'PS$BQUVSF͕*3ϊʔυΛॻ͖׵͍͑ͯͦ͏ʂ ͜͜ΛಡΊ͹উͪ΍ʂ ϑϥά MPPQWBSύοέʔδͷ಺෦࣮૷ΛಡΉ தؒදݱ *3 ࡞੒ ɾࣈ۟ղੳ

    ɾܕνΣοΫ ɾ*3 தؒදݱ ม׵ ϛουΤϯυ࠷దԽ ɾσουίʔυ࡟আ ɾΠϯϥΠϯԽ ɾԾ૝Խղআ ɾϧʔϓม਺ͷ҉໧తͳ࠶ఆٛ ɾΤεέʔϓղੳ 44"ม׵ ɾ੩త୯Ұ୅ೖܗࣜʹม׵ ػցޠม׵ ɾ֤؀ڥͷϚγϯޠʹม׵ 
  3. MPPQWBSύοέʔδͷ಺෦࣮૷ΛಡΉ·ͱΊ MPPQWBSύοέʔδͷ಺෦࣮૷ΛಡΉ MPPQWBSύοέʔδʹ͍ͭͯ ɾ(P͔Βϧʔϓม਺ͷ҉໧తͳ࠶એݴ͕ߦΘΕΔΑ͏ʹͳͬͨ ɾϧʔϓม਺҉໧తͳ࠶એݴͷ৚݅͸ΞυϨεऔಘPSΫϩʔδϟΩϟϓνϟ͞Εͨ࣌Ͱ͋Δ ɾϛουΤϯυ࠷దԽͷMPPQWBSύοέʔδ͕ɺதؒදݱ *3 ϊʔυΛॻ͖׵͑Δ͜ͱͰͦΕΛ࣮ݱ͍ͯ͠Δ ࣍ճ༧ࠂ ɾ҉໧తͳϧʔϓม਺ͷ࠶એݴ͕ߦΘΕ͍ͯΔʹ΋͔͔ΘΒͣ

    ɹ֤ΠςϨʔγϣϯʹ͓͚Δϧʔϓม਺ͷΞυϨε͕ಉ͜͡ͱ΋͋Ε͹ҟͳΔ͜ͱ΋͋Δ QSJOUMOGNU1SJOUMO  ɾϧʔϓͷڍಈͷҧ͍͸Τεέʔϓղੳʹݤ͕͋Γͦ͏ l҉໧తͳ࠶ఆٛzͷΠϝʔδ CFGPSF GPSWSBOHF\ GNU1SJOUMO W  ^ BGUFS GPSWSBOHF\ @WW GNU1SJOUMO @W  ^ 
  4. ώʔϓͱελοΫͱ͸ ώʔϓͱελοΫɺΤεέʔϓղੳ IUUQTTQFBLFSEFDLDPNZNPUPOHQPPNFNPSZNBOBHFNFOUJOHP ελοΫ ɾ֤HPSPVUJOF͕؅ཧ͢ΔϝϞϦྖҬ αΠζ͕ಈతʹ৳ॖ  ɾϨΩγΧϧείʔϓ಺ͷ ϥΠϑαΠΫϧΛ੩తʹ༧ଌͰ͖Δ σʔλΛѻ͏

    ϩʔΧϧม਺ͳͲ  ɾ-*'0ͰׂΓ౰ͯͱղ์͕ߴ଎ ώʔϓ ɾओʹϨΩγΧϧείʔϓ֎ͷ ϥΠϑαΠΫϧΛ༧ଌͰ͖ͳ͍ σʔλΛѻ͏ άϩʔόϧม਺ͳͲ  ɾׂΓ౰ͯͱղ์͕஗͍ɻ($ʹ૟আΛ೚ͤΔඞཁ͕͋Δɻ ͳΔ΂͘ελοΫΛ࢖༻͢Δ ώʔϓʹୀආ͞Εͳ͍ Α͏ʹ͍ͨ͠ 
  5. Τεέʔϓղੳͱ͸ ɾσʔλׂΓ౰ͯΛώʔϓʹΤεέʔϓͤ͞Δඞཁ͕͋Δͷ͔Λ൑ผ͢Δػߏ σϑΥϧτ͸ελοΫ  ɾϛουΤϯυ࠷దԽͷޙ൒ʹҐஔ͢Δ ߏจղੳͱ44"ܗࣜม׵ͷؒ  ɾؔ਺͕SFUVSOޙ΋σʔλ͕ࢀর͞Ε͏Δ৔߹ɺώʔϓ΁ͷׂΓ౰ͯ Τεέʔϓ ͕ൃੜ͢Δ

    ɾڧྗͳ($γεςϜͷݩɺݱঢ়Τεέʔϓղੳ͸อकతʹඞཁҎ্ʹσʔλΛΤεέʔϓͯ͠͠·͏ ɾHDGMBHTͷNΦϓγϣϯͰΤεέʔϓղੳ݁ՌΛӾཡͰ͖Δ IUUQTHPEFWXJLJ$PNQJMFS0QUJNJ[BUJPOTFTDBQFBOBMZTJT IUUQTUJQHPMBOHPSHEPDGBRTUBDL@PS@IFBQ ώʔϓͱελοΫɺΤεέʔϓղੳ 
  6.  ΞηϯϒϦΛݟͯΈΔɹTUFQελοΫϙΠϯλ 41 ΛόΠτݮΒ͢ ελοΫϙΠϯλ 41 Εͨ͢͡ ͨͬ͘͢ ॳظελοΫϙΠϯλ 41

    ελοΫϙΠϯλ 41 ͱ͸ ɾલఏελοΫྖҬ͸ΞυϨεͷߴ͍Ґஔ͔Β࢖༻͞ΕΔ ɾͲ͜ͷΞυϨε·ͰελοΫ͕٧·͍ͬͯΔ͔Λࣔ͢ τοϓΞυϨεϙΠϯλ ώʔϓͱελοΫɺΤεέʔϓղੳ 
  7. Τεέʔϓղੳ͓͞Β͍ ɾσʔλׂΓ౰ͯΛώʔϓʹΤεέʔϓͤ͞Δඞཁ͕͋Δͷ͔Λ൑ผ͢Δػߏ σϑΥϧτ͸ελοΫ  ɾϛουΤϯυ࠷దԽͷޙ൒ʹҐஔ͢Δ ߏจղੳͱ44"ܗࣜม׵ͷؒ  ɾؔ਺͕SFUVSOޙ΋σʔλ͕ࢀর͞Ε͏Δ৔߹ɺώʔϓ΁ͷׂΓ౰ͯ Τεέʔϓ ͕ൃੜ͢Δ

    ɾڧྗͳ($γεςϜͷݩɺݱঢ়Τεέʔϓղੳ͸อकతʹඞཁҎ্ʹσʔλΛΤεέʔϓͯ͠͠·͏ ɾHDGMBHTͷNΦϓγϣϯͰΤεέʔϓղੳ݁ՌΛӾཡͰ͖Δ IUUQTHPEFWXJLJ$PNQJMFS0QUJNJ[BUJPOTFTDBQFBOBMZTJT IUUQTUJQHPMBOHPSHEPDGBRTUBDL@PS@IFBQ ώʔϓͱελοΫɺΤεέʔϓղੳ 
  8. ·ͱΊ MPPQWBSύοέʔδʹ͍ͭͯ ɾ(P͔Βϧʔϓม਺ͷ҉໧తͳ࠶એݴ *3ϊʔυվม ͕ߦΘΕΔΑ͏ʹͳͬͨ ɾ҉໧తͳ࠶એݴͷ৚݅͸ɺϧʔϓม਺ͷΞυϨεऔಘPSΫϩʔδϟΩϟϓνϟͰ͋Δ Τεέʔϓͱϧʔϓ ɾϧʔϓ಺Ͱએݴ͞Εͨม਺͕ελοΫׂΓ౰ͯͷ৔߹ ɹ֤ΠςϨʔγϣϯͰಉ͡ΞυϨεΛ࣋ͪɺελοΫྖҬ͕࠶ར༻͞ΕΔ ɾϧʔϓ಺Ͱએݴ͞Εͨม਺͕ώʔϓׂΓ౰ͯͷ৔߹

    ɹ֤ΠςϨʔγϣϯͰҟͳΔΞυϨεΛ࣋ͪɺ($ʹΑΔղ์·ͰώʔϓྖҬΛ઎༗͢Δ ɾGNU1SJOUܥؔ਺ͷҾ਺͸Τεέʔϓ͢ΔҰํɺϏϧτΠϯͷQSJOUܥؔ਺͸Τεέʔϓ͠ͳ͍ ɹΑͬͯϧʔϓม਺ͷΞυϨεग़ྗͷ݁Ռʹҧ͍͕ੜ͡Δ पลπʔϧʹ͍ͭͯ ɾηϚϯςΟΫεมߋʹରԠ͢ΔͨΊʹHDGMBHT΍CJTFDUͳͲଟ͘ͷपลπʔϧͷαϙʔτ͕͋Δ ɾLBSBNBSVBMQIBDPQZMPPQWBSͷΑ͏ʹ ɹݴޠͷΞοϓσʔτۦಈͰMJOUFSΛ࡞੒͢Δͷ͸044ॳ৺ऀʹ΋νϟϯε͕໌֬Ͱ͓͢͢Ί