Go maps.Collect: สร้าง map จาก iterator คู่ key-value
เมื่อข้อมูลไหลมาเป็นคู่ key-value ผ่าน iter.Seq2 เราสร้าง map ด้วย maps.Collect ได้โดยไม่ต้องเขียนลูป boilerplate ครับ จุดสำคัญคือถ้า key ซ้ำ ค่าหลังสุดจะทับค่าก่อนหน้า จึงต้องตัดสินใจว่า behavior นี้ตรงกับกติกาธุรกิจหรือไม่
WHY: ติดป้ายช่องเก็บ แต่ป้ายซ้ำต้องมีกติกา
เหมือนพนักงานรับของที่วางสินค้าในช่องตามป้าย ถ้าป้ายเดิมมาถึงอีกครั้ง เขาจะเปลี่ยนของในช่องนั้น ไม่ได้สร้างช่องใหม่ ความสะดวกของ collector จึงไม่แทน validation หาก duplicate หมายถึงข้อมูลเสียต้องตรวจและคืน error ก่อน collect
package main
import (
"iter"
"maps"
"testing"
)
func entries() iter.Seq2[string, int] {
return func(yield func(string, int) bool) {
for _, pair := range []struct {
key string
val int
}{{"mint", 1}, {"forest", 2}, {"mint", 3}} {
if !yield(pair.key, pair.val) {
return
}
}
}
}
func TestCollect(t *testing.T) {
got := maps.Collect(entries())
if got["mint"] != 3 || got["forest"] != 2 || len(got) != 2 {
t.Fatalf("unexpected map: %#v", got)
}
empty := maps.Collect(func(func(string, int) bool) {})
if len(empty) != 0 {
t.Fatalf("expected empty map: %#v", empty)
}
}
Collection ไม่ใช่ validation
อย่าใช้ค่าทับกันเป็น default หาก config ซ้ำอาจซ่อนความผิดพลาดหรือเปิดช่องให้ input ท้ายสุดเปลี่ยน policy ทำ wrapper ที่เก็บ seen แล้วหยุดพร้อม error ก่อน Collect หรือเขียนลูปตรง ๆ เมื่อ error เป็นส่วนหนึ่งของ contract
Map ที่ได้ไม่รักษาลำดับ และ element ที่เป็น pointer ยังชี้ object เดิม หากต้อง deterministic output ให้ sort key ตอน serialize ไม่ควรพึ่ง iteration order
Recap
- ใช้
maps.Collectกับiter.Seq2ที่ไว้ใจ duplicate policy แล้ว - จำว่า key ซ้ำใช้ค่าหลังสุด
- แยก validation/error path ก่อน collection
- sort key เมื่อต้องการ output ที่ทำซ้ำได้