Go maps.Insert: เติม map จาก iterator โดยไม่ต้องเขียน loop ซ้ำ
เวลาเรามีข้อมูลเป็นคู่ key/value จาก iterator แล้วอยากเทลง map ปลายทาง การเขียน for k, v := range seq ทุกจุดไม่ได้ผิด แต่ทำให้คำสั่งธุรกิจ “เอาชุดนี้ไปเติม map” จมหายอยู่ในพิธีการครับ ตั้งแต่ Go 1.23 maps.Insert รับ iter.Seq2[K, V] แล้วใส่ทุกคู่ให้ตรงความหมายในบรรทัดเดียว
ลองนึกถึงพนักงานส่งบัตรคิวเป็นคู่ “ชื่อโต๊ะ–จำนวนคน” ช่องรับไม่ต้องรู้ว่าคู่เหล่านั้นมาจาก slice, parser หรือ generator ขอเพียงส่งตามสัญญา Seq2 ก็พอ
package main
import (
"fmt"
"maps"
)
func activeScores(yield func(string, int) bool) {
for _, item := range []struct {
name string
score int
}{{"mai", 7}, {"guy", 9}, {"mai", 10}} {
if !yield(item.name, item.score) {
return
}
}
}
func main() {
scores := map[string]int{"old": 1}
maps.Insert(scores, activeScores)
if scores["mai"] != 10 || scores["guy"] != 9 || scores["old"] != 1 {
panic("maps.Insert result is wrong")
}
fmt.Println(scores["mai"], scores["guy"])
}
คู่ที่มี key ซ้ำจะเขียนทับค่าก่อนหน้า ดังนั้นตัวอย่างได้ mai = 10 ไม่ใช่ 7 และ entry เดิมที่ไม่มี key ซ้ำยังอยู่ครบ ฟังก์ชันนี้จึงเป็น insert/overwrite ไม่ใช่ replace ทั้ง map หากต้องการ snapshot ใหม่ให้สร้าง map ใหม่ก่อน แล้วค่อย Insert
ลำดับของ map ใน Go ไม่รับประกัน อย่าพึ่งลำดับตอนอ่านผล และอย่าใช้เมื่อ key ซ้ำต้องถือเป็น error เพราะ Insert ไม่มี callback แจ้ง conflict กรณีนั้น loop ชัดกว่า: ตรวจ _, exists := dst[k] แล้วคืน error พร้อมบริบทได้
Recap
- ใช้เมื่อข้อมูลต้นทางเป็น
iter.Seq2และกติกาคือเขียนทับได้ - จำว่า map เดิมไม่ได้ถูกล้าง
- ตรวจ key ซ้ำเองเมื่อ conflict เป็นข้อผิดพลาด
- อย่าผูกผลลัพธ์กับลำดับ iteration ของ map