ข้ามไปยังเนื้อหา

Variables และ Types

Go มีสองวิธีในการประกาศตัวแปร:

var declaration — รูปแบบเต็ม สามารถใช้ได้ทั้งใน package level และใน function:

var name string // ประกาศพร้อม zero value
var age int = 30 // ประกาศพร้อมกำหนดค่าและระบุ type
var pi = 3.14159 // ประกาศพร้อมกำหนดค่า Go อนุมาน type ให้

Short declaration := — ใช้ได้เฉพาะใน function เหมาะสำหรับใช้งานทั่วไป:

name := "gopher" // Go อนุมาน type เป็น string
age := 30 // Go อนุมาน type เป็น int
pi := 3.14159 // Go อนุมาน type เป็น float64

:= ต้องมีตัวแปรใหม่อย่างน้อยหนึ่งตัวทางซ้าย ถ้าทุกตัวมีอยู่แล้วต้องใช้ =

ตัวแปรที่ประกาศโดยไม่กำหนดค่าจะได้รับ zero value โดยอัตโนมัติ ไม่มี uninitialized memory ใน Go:

TypeZero Value
int, int8, int16, int32, int640
uint, uint8, uint16, uint32, uint640
float32, float640.0
boolfalse
string"" (string ว่าง)
rune (alias สำหรับ int32)0
byte (alias สำหรับ uint8)0
pointer, slice, map, channel, functionnil

Go มี numeric types ที่หลากหลายพร้อมขนาดที่ชัดเจน:

var i int // ขนาดขึ้นกับ platform (32 หรือ 64 bit)
var i64 int64 // 64-bit signed integer เสมอ
var u uint32 // 32-bit unsigned integer
var f float64 // double precision floating point
var b bool // true หรือ false
var s string // sequence ของ UTF-8 bytes
var r rune // Unicode code point (int32)
var bt byte // raw byte (uint8)

ใช้ int เป็น default สำหรับ integers ยกเว้นมีเหตุผลเฉพาะที่ต้องใช้ขนาดอื่น

Constants ใน Go ยังไม่มี type จนกว่าจะนำไปใช้ (untyped constants) ทำให้ใช้ได้ยืดหยุ่น:

const Pi = 3.14159 // untyped float constant
const Limit = 100 // untyped integer constant
const Greeting = "hi" // untyped string constant

iota คือ counter พิเศษใน const block ที่เริ่มจาก 0 และ increment ทีละ 1 ทุก constant:

type Direction int
const (
North Direction = iota // 0
East // 1
South // 2
West // 3
)

Go ไม่มี implicit type conversion คุณต้องแปลงอย่างชัดเจนด้วย T(value):

var x int = 10
var y float64 = float64(x) + 0.5 // ต้องแปลง x ก่อน
var z int = int(y) // ตัดทศนิยมออก ไม่ปัดเศษ
s := strconv.Itoa(x) // int → string
n, _ := strconv.Atoi(s) // string → int (พร้อม error ที่ ignore ด้วย _)
package main
import "fmt"
type Weekday int
const (
Monday Weekday = iota + 1
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
)
func main() {
// Zero values
var i int
var s string
var b bool
fmt.Println("Zero int:", i)
fmt.Println("Zero string:", s == "")
fmt.Println("Zero bool:", b)
// Short declaration
name := "Go"
version := 1.22
fmt.Println("Language:", name, "Version:", version)
// iota enum
fmt.Println("Monday =", Monday)
fmt.Println("Wednesday =", Wednesday)
fmt.Println("Sunday =", Sunday)
// Explicit type conversion
meters := 100
kilometers := float64(meters) / 1000.0
fmt.Println("100 meters =", kilometers, "km")
// rune vs byte
ch := 'Z'
fmt.Println("rune 'Z' as int32:", int32(ch))
fmt.Println("byte value:", byte(ch))
}
สิ่งที่ได้ประโยชน์ต้นทุน
static typingcompiler จับ type mismatch ก่อน runtimeเขียน type annotation มากขึ้น
zero valuesไม่มี uninitialized variable, ไม่มี null dereferenceต้องเช็คว่า zero value มีความหมายในบริบทนั้นหรือเปล่า
no implicit conversionไม่มี hidden precision lossต้องเขียน float64(x) ทุกครั้งที่แปลง type
iota enumสร้าง enum ได้กระชับไม่มี built-in string representation — ต้องเขียน String() method เอง
  • int มีขนาด 32-bit เสมอ” — ขนาดของ int ขึ้นกับ platform (32-bit บน 32-bit OS, 64-bit บน 64-bit OS) ถ้าต้องการ size คงที่ ใช้ int32 หรือ int64
  • var x = y กับ x := y เหมือนกันเสมอ”:= ใช้ได้เฉพาะใน function scope เท่านั้น ไม่สามารถใช้ที่ package scope ได้
  • “zero value ของ pointer คือ 0” — zero value ของ pointer, slice, map, channel, และ function คือ nil ไม่ใช่ตัวเลข 0

💡 ตัวอย่างจากของจริง

Cloudflare ใช้ static typing ของ Go ในการป้องกัน bug ที่เกิดจาก type mismatch ใน edge routing logic — compiler จับ error ก่อนที่จะ deploy

Dropbox ย้ายจาก Python มา Go บางส่วน เพราะ static type system ทำให้ refactor codebase ขนาดใหญ่ได้ปลอดภัยกว่า

อะไรคือ zero value ของตัวแปร `string` ใน Go?
กำหนด `const ( A = iota; B; C )` ค่าของ C คือเท่าไร?
ข้อใดแปลง int เป็น float64 ได้ถูกต้องใน Go?
ตรงไหนที่ **ไม่สามารถ** ใช้ short declaration `:=` ได้?