Go maps.EqualFunc: เทียบ config คนละชนิดด้วยกติกาเดียว
เวลาเทียบ config ที่อ่านจากไฟล์กับสถานะที่ได้จาก API ชนิดข้อมูลมักไม่เหมือนกัน ฝั่งหนึ่งอาจเก็บจำนวนเป็น int อีกฝั่งเป็น int64 การวน map เองทำให้กฎเทียบกระจายอยู่หลายจุด maps.EqualFunc รับ comparator สำหรับ value สองชนิดและยังตรวจ key ให้ด้วยครับ
WHY: แยก “เดิน map” ออกจาก “ค่าเท่ากันแปลว่าอะไร”
เหมือนพนักงานเช็กสต็อกสองคลังที่ใช้แบบฟอร์มคนละสี เราไม่ต้องเขียนวิธีเดินทุกชั้นใหม่ เพียงกำหนดว่ากล่องสองใบถือว่าเป็นสินค้าเดียวกันเมื่อรหัสและจำนวนตรงกัน วิธีนี้ทำให้กฎ normalize อยู่ในฟังก์ชันเดียวและทดสอบได้ตรง ๆ
package content
import (
"maps"
"strings"
"testing"
)
type LocalLimit struct { Mode string; Max int }
type RemoteLimit struct { Mode string; Max int64 }
func limitsMatch(local map[string]LocalLimit, remote map[string]RemoteLimit) bool {
return maps.EqualFunc(local, remote, func(a LocalLimit, b RemoteLimit) bool {
return strings.EqualFold(strings.TrimSpace(a.Mode), strings.TrimSpace(b.Mode)) &&
int64(a.Max) == b.Max
})
}
func TestLimitsMatch(t *testing.T) {
local := map[string]LocalLimit{"upload": {Mode: " Strict ", Max: 8}}
remote := map[string]RemoteLimit{"upload": {Mode: "strict", Max: 8}}
if !limitsMatch(local, remote) { t.Fatal("normalized limits should match") }
remote["upload"] = RemoteLimit{Mode: "strict", Max: 9}
if limitsMatch(local, remote) { t.Fatal("different maximum must not match") }
remote["download"] = RemoteLimit{Mode: "strict", Max: 8}
if limitsMatch(local, remote) { t.Fatal("different key sets must not match") }
}
HOW: key ยังใช้ ==
Comparator รับเฉพาะ value ส่วน key ต้องเป็นชนิด comparable และเทียบด้วย == ตามเดิม ถ้าชื่อ key ไม่สนตัวพิมพ์เล็กใหญ่ ต้อง normalize ก่อนสร้าง map ไม่ใช่หวังให้ comparator ช่วย การ normalize ควรเหมือนกันทั้งสองฝั่งและจัดการ collision เช่น Admin กับ admin ให้ชัด
อย่าใช้ comparator ที่อ่านเวลา สุ่มค่า หรือแก้ state ภายนอก เพราะผลเทียบจะไม่เสถียร และอย่าแปลงตัวเลขกว้างเป็นชนิดแคบโดยไม่ตรวจช่วง ตัวอย่างขยาย int เป็น int64 จึงปลอดภัยบนค่าที่รับได้ของชนิดต้นทาง
Recap
- ใช้
EqualFuncเมื่อ value สอง map คนละชนิดหรือมีกฎเทียบเฉพาะโดเมน - normalize key ก่อนสร้าง map ถ้า key มี canonical form
- ทำ comparator ให้ deterministic และไม่มี side effect
- ตรวจการแปลงชนิดตัวเลขก่อนเปรียบเทียบ
- ทดสอบทั้ง value ต่างและชุด key ต่าง