Enums, Nested & oneof
enum: ชุด value ที่มีชื่อ
หัวข้อที่มีชื่อว่า “enum: ชุด value ที่มีชื่อ”enum คือ field ที่เป็นได้เพียงหนึ่งในชุด integer ที่มีชื่อกำหนดไว้ตายตัว enum สื่อ intent และกัน state ที่ไม่ถูกต้องได้ดีกว่า int32 หรือ string เปล่า ๆ มาก
enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_SUSPENDED = 2; STATUS_CLOSED = 3;}
message Account { int64 id = 1; Status status = 2;}กฎ zero value
หัวข้อที่มีชื่อว่า “กฎ zero value”มีกฎหนึ่งข้อที่ข้ามไม่ได้: value แรกของ enum ต้องเป็น 0 และควรหมายถึง “unspecified” เพราะ proto3 ไม่มี null ให้ scalar field enum ที่ไม่ถูก set จะอ่านได้เป็น zero value ถ้า 0 แปลว่า ACTIVE ทุก account ที่ลืม set status จะดูเหมือน active แบบเงียบ ๆ
flowchart TB unset["field ไม่ถูก set"] --> zero["อ่านได้เป็น value 0"] zero --> good["0 = UNSPECIFIED → ปลอดภัย เห็นชัดว่าไม่มีค่า"] zero --> bad["0 = ACTIVE → อันตราย ดูเหมือนตั้งใจ"]
convention (ที่ใช้ทั่ว API ของ Google) คือตั้งชื่อว่า <ENUM>_UNSPECIFIED = 0 ค่านี้ให้ state “ไม่มีค่า” ที่ชัดเจน และเก็บ value ที่มีความหมายไว้ให้การเลือกแบบตั้งใจ การเพิ่ม enum value ใหม่ภายหลังเป็น change ที่ปลอดภัยแบบ backward-compatible — client เก่าจะมองค่าที่ไม่รู้จักเป็น unknown เฉย ๆ
nested message
หัวข้อที่มีชื่อว่า “nested message”message ใส่ message อื่นข้างในได้ การ nest จัดกลุ่มข้อมูลที่เกี่ยวข้อง และให้ reuse type หรือจำกัด scope ของ type ไว้กับ message ที่เป็นเจ้าของ
message Order { int64 id = 1;
message LineItem { // scope อยู่ใน Order (Order.LineItem) string sku = 1; int32 quantity = 2; }
repeated LineItem items = 2; Address shipping = 3; // message ระดับบนสุดที่ reuse มาใช้ที่นี่}nest type เมื่อ type นั้นมีความหมายเฉพาะตอนอยู่ใน parent (Order.LineItem) และเก็บไว้ระดับบนสุดเมื่อหลาย message ใช้ร่วมกัน (Address)
oneof: เลือกได้อย่างเดียวจากหลาย field
หัวข้อที่มีชื่อว่า “oneof: เลือกได้อย่างเดียวจากหลาย field”oneof บอกว่า “set ได้มากสุดหนึ่ง field ในกลุ่มนี้ต่อครั้ง” การ set ตัวหนึ่งจะล้างตัวอื่น และ generated code ให้วิธีเช็กชัด ๆ ว่าตัวไหนถูก set
message Notification { int64 user_id = 1;
oneof channel { string email = 2; string sms_number = 3; string push_token = 4; }}ตรงนี้ notification ส่งออกผ่าน channel เดียวเป๊ะ ๆ oneof model “tagged union” ได้แม่นยำ — ดีกว่า field nullable สามตัวกับ comment ที่หวังว่าจะมีตัวเดียวถูกกรอกเยอะ และยังประหยัด memory เพราะ field เหล่านั้นใช้ storage ร่วมกัน