Types & Data
ภาพรวม Type ใน Go
หัวข้อที่มีชื่อว่า “ภาพรวม Type ใน Go”ทุกค่าใน Go มี type แบบ static ที่กำหนดตั้งแต่ compile time ซึ่ง Go แบ่ง type ออกเป็นสองกลุ่มหลัก:
Value types — ตัวแปรเก็บข้อมูลโดยตรง การ assign ค่าจะ copy ข้อมูลทั้งหมด ได้แก่ boolean, ตัวเลข (int, int64, float64, uint8, …), และ string รวมถึง composite value types อย่าง array และ struct
Reference-like types — ตัวแปรเก็บ header ขนาดเล็กที่ชี้ไปยังโครงสร้างข้อมูลจริงซึ่งถูก allocate ไว้ที่อื่น การ assign จะ copy แค่ header ดังนั้นตัวแปรสองตัวอาจชี้ไปข้อมูลชุดเดียวกันได้ ได้แก่ slice, map, channel, function, และ pointer
flowchart TD
Root["Go Type Taxonomy"]
Root --> Value["Value types (copy on assign)"]
Root --> Ref["Reference-like (header copied)"]
Value --> V1["bool, int, float64, string"]
Value --> V2["[N]T (array)"]
Value --> V3["struct { ... }"]
Ref --> R1["*T (pointer)"]
Ref --> R2["[]T (slice)"]
Ref --> R3["map[K]V"]
Ref --> R4["chan T, func(...)"] เนื้อหาในโมดูลนี้
หัวข้อที่มีชื่อว่า “เนื้อหาในโมดูลนี้”| บทเรียน | หัวข้อ |
|---|---|
| หน้านี้ | ภาพรวม Type และโปรแกรมตัวอย่างแรก |
| Structs | การนิยาม struct, embedding, การเปรียบเทียบ |
| Slices | Array vs slice, make, append, copy |
| Maps | make(map[K]V), comma-ok, delete, การวน loop |
| Pointers | & และ *, mutation, nil pointer |
โปรแกรม composite type แรกของคุณ
หัวข้อที่มีชื่อว่า “โปรแกรม composite type แรกของคุณ”โปรแกรมด้านล่างนิยาม struct ชื่อ Point สร้าง slice []Point แล้วค้นหาชื่อจาก map[string]int ซึ่งแสดงให้เห็น value type (Point ถูก copy), slice literal, และการเข้าถึง map พร้อม zero-value เมื่อ key ไม่มีอยู่
package main
import "fmt"
type Point struct { X, Y int}
func main() { // Struct literal with named fields p := Point{X: 3, Y: 4} fmt.Println(p.X, p.Y)
// Slice of structs points := []Point{ {X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, } for _, pt := range points { fmt.Printf("(%d, %d)\n", pt.X, pt.Y) }
// Map: string -> int score := map[string]int{ "Alice": 95, "Bob": 87, } fmt.Println(score["Alice"]) fmt.Println(score["Charlie"]) // missing key -> zero value (0)}Loading Go runtime (first run only, ~8 MB)…
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ประเภท | ประโยชน์ | ต้นทุน |
|---|---|---|
| value type (struct, array) | predictable behavior, ไม่มี aliasing | copy cost สำหรับ type ขนาดใหญ่ |
| reference-like type (slice, map) | แชร์ data โดยไม่ต้อง copy | shared mutation — goroutine หนึ่งแก้ไขอาจกระทบอีกตัว |
| static typing | compiler catch errors เร็ว | verbose type declarations |
| composite literals | readable initialization | syntax แตกต่างกันตาม type |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- array และ slice คือสิ่งเดียวกัน — array มีขนาดคงที่เป็นส่วนของ type เช่น
[3]int≠[4]int; slice เป็น dynamic view ของ array - map safe สำหรับ concurrent access — Go map ไม่ใช่ — ต้องใช้
sync.Mutexหรือsync.RWMutexถ้า goroutine หลายตัวอ่าน/เขียนพร้อมกัน - struct copy เสมอแพง — struct เล็ก (2-4 fields) copy เร็วมาก บางครั้งเร็วกว่าการใช้ pointer ที่ต้อง dereference และอาจ escape to heap
💡 ตัวอย่างจากของจริง
Kubernetes ใช้ slice สำหรับ pod list และ container list — แต่ละ reconcile loop สร้าง slice ใหม่ผ่าน append
Prometheus ใช้ map สำหรับ metric label —
map[string]stringเป็น label set หลักDocker ใช้ struct + pointer receiver สำหรับ container state management