Fix for-range Issue Again in Go 1.22

  sonic0002        2024-11-21 01:03:04       1,318        1          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

ด้วยการเปิดตัว Go 1.22 ทีม Go ได้แก้ไขปัญหาที่ยืนยงมาอย่างยาวนาน เกี่ยวกับขอบเขตตัวแปรวนซ้ำ for-range ซึ่งเป็นกับดักทั่วไปสำหรับนักพัฒนาที่เขียนโค้ดแบบขนาน โดยเฉพาะอย่างยิ่ง ปัญหาคือตัวแปรวนซ้ำในลูป for-range นั้นถูกนำกลับมาใช้ใหม่ในแต่ละรอบ ทำให้เกิดพฤติกรรมที่ไม่คาดคิดเมื่อมีการใช้ closures

ปัญหา ก่อน Go 1.22

ลองพิจารณาตัวอย่างต่อไปนี้:

package forange

import "fmt"

func Do() {
    done := make(chan bool)
    values := []string{"a", "b", "c"}

    for _, v := range values {
        go func() {
            fmt.Println(v) // พิมพ์ค่าที่ไม่คาดคิด
            done <- true
        }()
    }

    for _ = range values {
        <-done
    }
}

และมีไฟล์ go.mod ดังต่อไปนี้

module playground

go 1.16

require github.com/ozgio/strutil v0.4.0

ในเวอร์ชันของ Go ก่อน 1.22 การรันโค้ดนี้มักส่งผลให้พิมพ์ค่าเดียวกัน (เช่น c) หลายครั้ง แทนที่จะพิมพ์แต่ละค่าใน values (a, b, c) ตามที่คาดไว้ นี่เป็นเพราะตัวแปรวนซ้ำ v ถูกนำกลับมาใช้ใหม่ในแต่ละรอบ และ goroutines ได้จับที่อยู่หน่วยความจำเดียวกัน

การแก้ไข Go 1.22

Go 1.22 ได้แนะนำการแก้ไขพฤติกรรมนี้โดยทำให้ตัวแปรวนซ้ำทำงานราวกับว่ามันถูกประกาศใหม่ในแต่ละรอบ ซึ่งหมายความว่าแต่ละ closure ควรจับค่าของ v สำหรับการวนซ้ำที่ตรงกันได้อย่างถูกต้อง

อย่างไรก็ตาม หากคุณอัปเกรดเป็น Go 1.22 แล้วและยังคงเห็นพฤติกรรมเก่าที่เป็นปัญหาอยู่ ผู้กระทำผิดอาจเป็นไฟล์ go.mod ของคุณ การแก้ไขจะมีผลก็ต่อเมื่อไฟล์ go.mod ระบุเวอร์ชัน Go เป็น 1.22 หรือสูงกว่า การพึ่งพานี้เป็นเจตนาและอนุญาตให้นักพัฒนาคงความเข้ากันได้แบบย้อนหลังกับพฤติกรรมเก่าได้หากจำเป็น

เมื่อระบุ go 1.22 ใน go.mod ของคุณและมีการใช้การแก้ไข การรันโปรแกรมข้างต้นควรพิมพ์ a, b, c ได้อย่างถูกต้อง แต่ละ goroutine ตอนนี้จับค่าที่เหมาะสมของ v สำหรับการวนซ้ำของมัน

บทเรียนที่ได้รับ

  • อัปเดตอยู่เสมอ: อ่านบันทึกย่อประจำการเผยแพร่สำหรับเวอร์ชัน Go ใหม่เสมอ บันทึกย่อประจำการเผยแพร่ Go 1.22 กล่าวถึงโดยเฉพาะ การเปลี่ยนแปลงนี้และการพึ่งพา go.mod
  • ใช้เวอร์ชัน go.mod ที่ถูกต้อง: คุณลักษณะภาษา Go หลายอย่างถูกผูกไว้กับเวอร์ชัน go ใน go.mod หากคุณกำลังพึ่งพาคุณลักษณะหรือการแก้ไขใหม่ โปรดตรวจสอบให้แน่ใจว่าได้ระบุเวอร์ชันที่ถูกต้อง
  • ทดสอบอย่างละเอียด: แม้หลังจากอัปเกรด Go แล้ว โปรดตรวจสอบให้แน่ใจว่าโปรแกรมของคุณทำงานได้ตามที่คาดไว้โดยการรันการทดสอบที่ครอบคลุม

เหตุใดการพึ่งพานี้จึงจำเป็น

วิธีการเวอร์ชัน go.mod ช่วยให้ทีมต่างๆ สามารถนำการแก้ไขมาใช้ได้ทีละน้อยโดยไม่ทำลายการสร้างที่มีอยู่ โดยการเชื่อมโยงพฤติกรรมภาษาใหม่กับเวอร์ชัน go ใน go.mod ทีม Go จึงมั่นใจได้ถึงความเข้ากันได้แบบย้อนหลังในขณะที่ช่วยให้การโยกย้ายสำหรับนักพัฒนาเป็นไปอย่างราบรื่นยิ่งขึ้น

หากคุณเคยประสบกับความท้าทายที่คล้ายคลึงกันหรือมีข้อมูลเชิงลึกเกี่ยวกับวิธีการที่ส่งผลกระทบต่อเวิร์กโฟลว์ของคุณ โปรดแบ่งปันในความคิดเห็น!

BUG  GO  FOR RANGE  GO.MOD  GO 1.22 

       

  RELATED


  1 COMMENT


xieyonglin [Reply]@ 2024-11-21 06:43:57

Nice article?



  RANDOM FUN

Unable to connect to the Internet

When the Windows prompt you that "Unable to connect to the Internet, would you like to search online for solutions?". What would be your next reaction? Tell me. I promise I will not tell anyone else.