กระรอก Go สีฟ้าเขียวทดลองจัดข้อมูลบนโต๊ะทำงาน โทนสว่างสีมิ้นต์และครีม

Go Serialization 03: Protobuf จาก schema ถึง generated code

พี่โชว์Engineering

Protobuf เพิ่มขั้นตอนสร้าง schema แต่ทำให้สัญญาระหว่างระบบชัดขึ้นครับ บทนี้เราจะดูทั้งไฟล์ .proto และ adapter ที่เปลี่ยนระหว่าง struct ของแอปกับ generated message

เตรียมโปรเจกต์

ดาวน์โหลด โปรเจกต์ Go พร้อม schemas, generated code, tests และผลดิบ แล้วแตกไฟล์ ใช้ Go 1.27 ขึ้นไป เปิด terminal ในโฟลเดอร์ go-api-serialization และรัน go mod download ครั้งแรก ไม่ต้องติดตั้ง compiler ของ schema เพื่อเริ่มเรียน

โค้ดบนหน้านี้เป็นตัวอย่างบางส่วน (fragment) เพื่ออธิบายจุดสำคัญ คำสั่ง shell ตรวจ syntax ส่วน โปรเจกต์เต็มตรวจด้วย go test ./... ใน quality gate ไม่ควรนำ fragment ไปรันเป็นโปรแกรมเดี่ยว

1. อ่าน schema

เปิด schemas/catalog.proto ตัวอย่างบางส่วน:

message Product {
  int64 id = 1;
  string name = 2;
  int64 price_cents = 3;
  bool in_stock = 4;
  repeated string tags = 5;
}
message Catalog { repeated Product products = 1; }

เลขข้างชื่อฟิลด์คือส่วนหนึ่งของ wire contract ไม่ใช่ลำดับแสดงผล ห้ามนำหมายเลขฟิลด์ที่เลิกใช้กลับไปแทนความหมายใหม่ การเพิ่ม/ลบฟิลด์ต้องทบทวน compatibility และ default values โดย empty protobuf bytes เป็น Catalog ว่างที่ถูกต้อง

2. ใช้ generated code ที่ตรวจแล้ว

go test -run 'TestRoundTrip/protobuf|TestInvalidInputs/protobuf' -v
go test -run '^$' -bench 'BenchmarkCodecs/protobuf' -benchmem -benchtime=300ms -count=5

ผลที่ตรวจได้: tests ผ่านทั้ง int64 ขอบบนและภาษาไทย มีไฟล์ internal/pb/catalog.pb.go อยู่ใน ZIP แล้ว การวัด encode รวมการสร้าง generated message และ decode รวมการแปลงกลับเป็น Catalog จึงเป็นต้นทุนที่แอปนี้จ่ายจริง

3. สร้าง code ใหม่เมื่อเปลี่ยน schema

ติดตั้ง protoc 36.0 จากโครงการทางการและเพิ่มโฟลเดอร์ Go bin ใน PATH ก่อนรัน:

go install google.golang.org/protobuf/cmd/[email protected]
protoc --go_out=. --go_opt=module=workshop.local/serialization schemas/catalog.proto
go test ./...

ผลที่ตรวจได้: generated header ระบุ protoc-gen-go v1.36.12 และ protoc v36.0 การรันซ้ำโดยไม่เปลี่ยน schema ควรได้ code เดิม การ build/read schema ไม่อยู่ในเวลา benchmark

แบบฝึกหัด

เพิ่มฟิลด์ currency ด้วยหมายเลขใหม่ แล้วเติม adapter ทั้ง encode และ decode เพิ่ม assertion ให้ tests ตรวจค่านั้น ลองอ่าน payload เก่าด้วย schema ใหม่และบันทึกค่า default ที่ได้ อย่าเพียงเปลี่ยน schema แล้วถือว่าแอปรองรับฟิลด์ใหม่ครบแล้ว

อ่านต่อ