Golang เป็นภาษาที่มีประเภทของ Integer มากกว่าภาษาอื่นบางภาษา จากตัวเลือกที่ค่อนข้างเยอะ บางครั้งเราอาจสงสัยว่าเมื่อใดที่เราควรใช้ Integer ประเภทใด บทความนี้แนะนำการเลือกใช้ Integer ใน Golang ครับ
ก่อนที่เราจะไปดูหลักเกณฑ์ในการเลือกใช้ เรามาดูกันก่อนว่า Golang มี Integer กี่แบบ
ประเภท | ขนาด | ช่วงของข้อมูลที่เก็บได้ |
---|---|---|
int8 | 8 bits | -128 ถึง 127 |
int16 | 16 bits | -32768 ถึง 32767 |
int32 | 32 bits | –2147483648 ถึง 2147483647 |
int64 | 64 bits | –9223372036854775808 ถึง 9223372036854775807 |
uint8 | 8 bits | 0 ถึง 255 |
uint16 | 16 bits | 0 ถึง 65536 |
uint32 | 32 bits | 0 ถึง 4294967295 |
uint64 | 64 bits | 0 ถึง 18446744073709551615 |
นอกจากนี้ Golang ยังมี int และ uint ซึ่งขนาดของมันสามารถเป็นได้ทั้ง 32 bits หรือ 64 bits ขึ้นกับ platform เช่น ถ้าบนเครื่อง 32-bits compiler ก็จะใช้ค่า int และ uint เป็น 32 bits
ในทางตรงข้าม ถ้าบนเครื่อง 64-bits ส่วนใหญ่แล้ว compiler ก็จะใช้ค่า int และ uint เป็น 64 bits (แต่จาก FAQ ของ Golang เค้าบอกว่าไม่ได้เป็นอย่างนี้เสมอไป แต่ก็ไม่ได้ให้ข้อมูลอะไรเพิ่มเติม และผมเองก็หาข้อมูลเพิ่มเติมไม่ได้ด้วยครับ)
Zero value
ถึงแม้ Golang จะมีประเภทของ Integer หลายประเภท แต่ค่า zero value ของ Integer ทุกประเภท คือ 0
เลือกประเภทของ Integer
เมื่อเรารู้จัก Integer แต่ละประเภทใน Golang แล้ว การเลือกว่าจะใช้ Integer ประเภทใด มีหลักที่เรียบง่ายอยู่ 3 ข้อ คือ
1. ถ้ารู้ขนาดและเครื่องหมาย
ถ้าเราทำงานกับ Binary file หรือ Network protocol หรือข้อมูลที่เรารู้ขอบเขตของขนาดข้อมูลและเครื่องหมายว่าเป็นจำนวนเต็มบวกหรือลบอย่างแน่นอนล่วงหน้าแล้ว ให้เราเลือกใช้ Integer เจาะจงประเภทใดประเภทหนึ่งจากตารางข้างบนไปเลย
2. ถ้าต้องรองรับ Integer ประเภทใดก็ได้
ถ้าเราต้องเขียน Function ที่ควรทำงานกับจำนวนเต็มประเภทใดก็ได้ ให้เขียน function มาคู่หนึ่ง โดยที่ function หนึ่งมี parameter เป็น int64 และอีก function หนึ่งมี parameter เป็น uint64
💡 เราสามารถเห็น pattern นี้ได้ใน Go standard library เช่น ฟังก์ชัน FormatInt / FormatUint หรือ ParseInt / ParseUint ใน strconv package
เหตุผลที่ int64 และ uint64 เหมาะสมในสถานการณ์นี้ เพราะในตอนนี้ Golang ยังไม่มี Generics (เฉพาะตอนนี้) และ Golang ไม่มี Function Overloading อีกด้วย จากเหตุผลเหล่านี้ ส่งผลให้เราต้องเขียนหลาย Function และต้องตั้งชื่อให้ต่างกัน
การใช้ int64 และ uint64 ช่วยให้เราเขียน Function แค่ครั้งเดียว แล้วให้ผู้ที่เรียกใช้แปลงค่า Arguments ที่จะส่งให้ Function และแปลงค่าที่รับคืนจาก Function ได้เองไม่ยากนัก
💡 แต่ถ้าขนาดของ Integer มีความสำคัญ เราควรเขียน Function แยกให้กับ Integer แต่ละประเภท เหมือนกับ math/bits package
3. กรณีอื่น ๆ
กรณีอื่น ๆ นอกจากข้อ (1) และ (2) ให้ใช้ int
จนกว่าเราจะมีข้อพิสูจน์ที่ชัดเจนถึงเรื่องขนาดและเครื่องหมายของจำนวนเต็ม เราจึงค่อยเปลี่ยนไปใช้ Integer ประเภทอื่นเพื่อเพิ่มประสิทธิภาพครับ
อ้างอิง
- หนังสือ “Learning Go” สำนักพิมพ์ O’Reilly
- https://golang.org/doc/faq
- https://golang.org/ref/spec
- https://groups.google.com/g/golang-nuts/c/mtnn-01Dh_I