DEV Community

Pallat Anchaleechamaikorn
Pallat Anchaleechamaikorn

Posted on

proposal เรื่อง loop variable scoping ที่จะมาใน go 1.22

#go

มีประเด็นน่าสนใจที่จะถูกเปลี่ยนแปลงใน go1.22 ที่จะมาถึงนี้เรื่องนึง สามารถดูอ้างอิงได้ที่นี่ https://github.com/golang/go/issues/60078

โดยเนื้อหาคร่าวๆคือ เรื่อง scope ของตัวแปรที่เราสร้างใน loop เช่น

func TestAllEven(t *testing.T) {
    testCases := []int{0, 2, 4, 6}
    for _, v := range testCases {
        t.Run("sub", func(t *testing.T) {
            t.Parallel()
            if v&1 != 0 {
                t.Fatal("odd v", v)
            }
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

ใน proposal บอกว่าเทสนี้ ความจริงอยากทดสอบว่าตัวเลขในลิสต์ 0,2,4,6 ทั้งหมดนี้ เป็นเลขคู่หรือไม่ ซึ่งถ้าพบเลขคี่ในลิสต์มันจะพิพม์ออกมาว่า odd x แทนที่ x ด้วยเลขคี่นั้นๆ

แต่ในปัจจุบัน go จะสร้าง instance ของ v เพียง 1 instance ต่อ loop ทั้งหมด นั่นหมายความว่า เมื่อเรารันเทสนี้ มันจะเทสที่เลข 6 เลขเดียวทั้ง 4 loop เนื่องจากเราสั่งให้มันรันแบบ parallel

โดย proposal นี้จะทำการแก้ไขให้มันสร้าง instance ใหม่ในทุกๆ iteration แทนที่จะสร้างเพียงแค่ 1 instance ให้ทุกๆ iteration ซึ่งจะมีผลทำให้เมื่อเราเอาเทสนี้ไปรันใน g1.22 มันจะสามารถเช็คเลขครบทุกตัว ตั้งแต่ 0, 2, 4 และ 6 ได้ตามที่เราคาดหวัง

ทีนี้ก็มีคนเอา code อีกชุดนึงมาเสนอว่าถ้าเป็นแบบนี้ล่ะ ใน go1.22 มันจะเปลี่ยนไปเป็นอย่างไร อ้างอิงจาก https://twitter.com/go100and1/status/1657230061777592320

package main

func main() {
  for counter, i := 0, 0; i < 3; i++  {
    defer func() {
      counter++
      print(counter)
    }()
  }
}
Enter fullscreen mode Exit fullscreen mode

จากโค้ดชุดนี้เมื่อนำมารัน จะได้ผลลัพธ์ 123 เนื่องจาก counter ถูกสร้างเพียง 1 instance สำหรับทุก iteration แต่เมื่อเรานำโค้ดนี้ไปรันใน go1.22 มันจะได้ผลลัพธ์เป็น 111 แทน

โดยการเปลี่ยแปลงนี้น่าจะ apply เฉพาะโค้ดที่ระบุ Go version ที่ใหม่พอ (เดาว่า g0 1.22) ไม่งั้นอาจจะกระทบโค้ดเก่าๆของเราเยอะพอสมควรเลยดีเดียวครับ

Top comments (1)

Collapse
 
stankukucka profile image
Stan Kukučka

@pallat รหัสอร่อย :)