พื้นฐานและ Syntax
ปรัชญาการออกแบบของ Go
หัวข้อที่มีชื่อว่า “ปรัชญาการออกแบบของ Go”Go ถูกออกแบบมาโดยยึดสี่แนวคิดที่ส่งผลต่อทุกสิ่งที่คุณเขียน
ความเรียบง่ายเหนือความฉลาดเกินไป (Simplicity over cleverness) ภาษามี spec เล็ก มี keyword เพียง 25 คำ ตั้งใจไม่มี overloading, ไม่มี default arguments, ไม่มี implicit conversion, และไม่มี inheritance เมื่อคุณอ่าน code ของ Go ที่คนอื่นเขียน มันจะดูเหมือน code ที่คุณเองก็เขียนได้เกือบทุกจุด นั่นคือความตั้งใจ
Compile เร็ว (Fast compile) การ compile เร็วเป็นเป้าหมายการออกแบบตั้งแต่แรก ไม่ใช่สิ่งที่คิดทีหลัง — Go ถูกสร้างขึ้นที่ Google เพื่อแก้ปัญหา build ของ C++ ที่ช้าเป็นนาทีซึ่งผู้สร้างภาษาเจอมาโดยตรง การ compile แม้แต่ codebase ขนาดใหญ่มักใช้เวลาแค่ไม่กี่วินาที ทำให้ loop แก้-compile-รัน สั้นและ iteration เร็ว
Explicit มากกว่า Implicit (Explicit over implicit) การแปลง type และการจัดการ error เป็นแบบ explicit ทั้งหมด ไม่มีอะไรเกิดขึ้นเบื้องหลังที่คุณไม่ได้เขียนเอง ค่าจะอยู่ที่ stack หรือ heap ถูกตัดสินใจโดย escape analysis ของ compiler ไม่ใช่จากสิ่งที่มองเห็นได้ตรงจุดเรียกใช้ — ดูบท Pointers เรื่องนี้ทำให้ code ตามรอยและตรวจสอบได้ง่าย
วิธีเดียวที่ชัดเจน (One obvious way) เครื่องมือของ Go บังคับ code style เดียว (gofmt), module system เดียว (go mod), และ test runner เดียว (go test) การถกเถียงเรื่อง formatting, ลำดับ import, และโครงสร้าง project จึงไม่เกิดขึ้นเลย
// The compiler rejects unused imports and unused local variables.// This keeps every file minimal and every dependency intentional.import "fmt"
func greet(name string) string { return "Hello, " + name}Go Program กลายเป็นอะไร
หัวข้อที่มีชื่อว่า “Go Program กลายเป็นอะไร”go build compile program ของคุณตรงไปเป็น native machine-code binary สำหรับ GOOS/GOARCH ของคุณ — ไม่มี bytecode และไม่มี virtual machine เข้ามาเกี่ยวข้องตอน runtime เลย ต่างจาก Java หรือ CPython interpreter บนเครื่องนี้ go build โปรแกรม “hello world” ไฟล์เดียวจะได้ executable แบบ self-contained ขนาดสองสามเมกะไบต์ (ส่วนใหญ่คือ Go runtime — scheduler กับ garbage collector — ที่ link เข้าไปใน binary โดยตรง) และรันมันต้องการแค่ operating system เท่านั้น: ไม่ต้องติดตั้ง Go ไม่ต้อง ship runtime แยกไปด้วย
go run เป็นแค่ตัวห่อความสะดวก ไม่ใช่ execution model คนละแบบ: มัน compile เป็น binary ชั่วคราวเบื้องหลังแล้วรันทันที จากนั้นทิ้ง binary นั้นไป มันเป็นวิธีเร็วที่สุดสำหรับลองอะไรตอนเรียนรู้ — playground ทุกตัวในเว็บนี้ทำงานแบบ go run — แต่สำหรับอะไรที่คุณ deploy หรือ benchmark ซ้ำ ๆ ให้ go build ครั้งเดียวแล้วรัน binary ที่ได้โดยตรง
โมดูลนี้ครอบคลุมอะไร
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไร”| บทเรียน | หัวข้อ |
|---|---|
| Variables และ Types | var, :=, zero values, const, iota, overflow, string ในฐานะ byte |
| Control Flow | if พร้อม init, for (สามรูปแบบ), labeled break/continue, switch |
| Functions | multiple return, defer, closure, first-class function, pass-by-value |
| Packages และ Imports | package, import, ลำดับ initialization, internal/, go.mod |
เมื่อจบโมดูลนี้คุณจะอ่านและเขียน idiomatic Go program แบบสมบูรณ์ตั้งแต่ต้นได้
โปรแกรมแรก
หัวข้อที่มีชื่อว่า “โปรแกรมแรก”ด้านล่างคือโปรแกรม Go ที่แสดงให้เห็น syntax พื้นฐาน: การประกาศตัวแปรด้วย :=, types หลายชนิด, และการ print ผลลัพธ์
package main
import "fmt"
func main() { name := "Go" version := 1.27 fast := true fmt.Println("Hello from", name) fmt.Println("Version:", version) fmt.Println("Fast compile:", fast)}รันด้านล่างเพื่อดู output ทุก concept ที่ใช้ที่นี่จะอธิบายอย่างละเอียดในบทเรียนต่อไป:
package main
import "fmt"
func main() { name := "Go" version := 1.27 fast := true fmt.Println("Hello from", name) fmt.Println("Version:", version) fmt.Println("Fast compile:", fast)
// Integer arithmetic is exact; no implicit float promotion a := 10 b := 3 fmt.Println("10 / 3 =", a/b) fmt.Println("10 % 3 =", a%b)} ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| สิ่งที่ได้ | ประโยชน์ | ต้นทุน |
|---|---|---|
| static typing | compiler จับ bug ก่อน runtime | เขียน code มากกว่า dynamic language เล็กน้อย |
| keyword เพียง 25 คำ | เรียนรู้เร็ว, อ่าน code คนอื่นได้ง่าย | feature บางอย่าง (เช่น generics ยุคแรก) ต้องใช้ workaround |
| fast compile | feedback loop สั้น, iteration เร็ว | ไม่มี REPL ที่สมบูรณ์แบบ |
| garbage collection | ไม่ต้องจัดการ memory เอง | GC pause ที่ unpredictable ใน latency-critical system |
| native binary ไม่มี VM | ไม่ต้องติดตั้ง runtime, startup เร็ว, deploy ง่าย (ไฟล์เดียว) | binary ใหญ่กว่า interpreted script; Go runtime ถูก link เข้าไปเสมอ |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- “Go คือ C เวอร์ชันใหม่” — Go มี GC, goroutine, interface, และ module system ที่แตกต่างจาก C โดยสิ้นเชิง
- “Go ไม่มี OOP” — Go มี struct, method, และ interface ที่ทำ composition ได้ แต่ไม่มี class hierarchy แบบ Java
- “Go ใช้ได้แค่ backend server” — Go ใช้งานได้กับ CLI tools, DevOps tooling, WebAssembly, embedded systems, และ data pipelines
- “
go runคือวิธีที่ Go program ควรถูกรันใน production” —go runเป็นแค่ความสะดวกตอนพัฒนาที่ compile เป็น binary ทิ้งขว้างทุกครั้ง; Go program ที่ deploy จริงจะ build ครั้งเดียวด้วยgo buildแล้ว ship binary ตัวนั้นออกไป
อ่านโค้ดที่ AI เขียน
หัวข้อที่มีชื่อว่า “อ่านโค้ดที่ AI เขียน”ตลอดทุกบทในโมดูลนี้ การตรวจไม่กี่ข้อเดียวกันนี้จับ bug ของ generated code ได้ส่วนใหญ่ก่อนที่มันจะถูกใช้จริง:
:=ในif/forใช้ชื่อ (มักเป็นerr) ที่มีอยู่แล้วใน scope ภายนอกซ้ำ หรือแอบประกาศตัวแปรใหม่ที่ shadow มันอยู่?breakอยู่ในswitch(หรือselect) ที่ตัวมันเองอยู่ในforหรือเปล่า? มันออกจากแค่ construct ข้างในเท่านั้น ไม่เคยออกจาก loopdeferอยู่ใน loop หรือเปล่า หรือdefer f.Close()ทิ้ง error ที่สำคัญไปหรือเปล่า?- function value หรือ struct field ที่เก็บมันอยู่ ถูกเรียกโดยไม่เช็ก
nilก่อนหรือเปล่า?
🐛 หา bug ในโค้ดนี้
type Config struct { OnReady func()}
func main() { c := Config{} c.OnReady()}เฉลย
OnReady เป็น field ชนิด function ที่ไม่เคยถูก assign ค่า จึงมี zero value เป็น nil การเรียก function value ที่เป็น nil จะ panic: runtime error: invalid memory address or nil pointer dereference นี่คือ bug ประเภทเดียวกับ nil pointer dereference — วิธีแก้คือเช็ก if c.OnReady != nil { c.OnReady() } ก่อนเรียก หรือให้ Config มี constructor ที่กำหนด default เป็น no-op function เสมอ