ด้วยการเปิดตัว 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 จึงมั่นใจได้ถึงความเข้ากันได้แบบย้อนหลังในขณะที่ช่วยให้การโยกย้ายสำหรับนักพัฒนาเป็นไปอย่างราบรื่นยิ่งขึ้น
หากคุณเคยประสบกับความท้าทายที่คล้ายคลึงกันหรือมีข้อมูลเชิงลึกเกี่ยวกับวิธีการที่ส่งผลกระทบต่อเวิร์กโฟลว์ของคุณ โปรดแบ่งปันในความคิดเห็น!
Nice article?