Pointers (ตัวชี้)
TypeScript ไม่มี pointer แบบ explicit
หัวข้อที่มีชื่อว่า “TypeScript ไม่มี pointer แบบ explicit”ใน TypeScript (และ JavaScript) object ถูกส่งต่อเป็น reference โดยอัตโนมัติ คุณไม่เคยต้องเขียนว่า “ขอ address ของตัวแปรนี้” เพราะ runtime จัดการ memory ให้เบื้องหลังโดยที่คุณมองไม่เห็น
Go เปิดเผย memory address อย่างชัดเจน คุณเลือกเองว่า function จะรับ copy ของค่าหรือ pointer ไปยังต้นฉบับ การเลือกนั้นมีผลจริงต่อความถูกต้องและประสิทธิภาพ
Operator & และ *
หัวข้อที่มีชื่อว่า “Operator & และ *”&x ให้ pointer ไปยัง x — address ใน memory ที่ x อาศัยอยู่
*p dereference pointer p — อ่านหรือเขียนค่าที่ address นั้น
// TypeScript — objects are implicitly sharedfunction increment(obj: { count: number }) { obj.count++; // mutates the original (reference)}
const counter = { count: 0 };increment(counter);console.log(counter.count); // 1
// BUT primitives are always copied:function addOne(n: number): number { return n + 1; // n is a copy — caller unchanged}let x = 5;addOne(x);console.log(x); // still 5// Go — primitives copied by default; use * to opt in to mutationfunc increment(n *int) { *n++ // dereference and mutate}
func main() { x := 42 increment(&x) // pass address of x fmt.Println(x) // 43 — x was mutated
// Without pointer — value is copied, caller unchanged // increment(x) would be a compile error (type mismatch)}Pointer types
หัวข้อที่มีชื่อว่า “Pointer types”ทุก type T มี pointer type *T ที่สอดคล้องกัน ตัวแปร pointer เก็บ address ไม่ใช่ค่า
// TypeScript has no pointer types// The closest is a wrapper object or ref pattern:const ref = { current: 0 }; // manual "pointer" idiomvar p *int // p is a pointer to int, value is nilx := 10p = &x // p now holds the address of xfmt.Println(*p) // 10 — dereference to read*p = 20 // write through pointerfmt.Println(x) // 20เมื่อไหร่ควรใช้ pointer ใน Go
หัวข้อที่มีชื่อว่า “เมื่อไหร่ควรใช้ pointer ใน Go”มีสองเหตุผลหลักในการใช้ pointer:
- Mutation — คุณต้องการให้ function แก้ไขตัวแปรของ caller (ไม่ใช่ทำงานกับ copy)
- Efficiency — struct มีขนาดใหญ่และการ copy ทุกครั้งที่เรียกจะสิ้นเปลือง
สำหรับ struct ขนาดเล็ก (2–3 field) ที่อ่านอย่างเดียว มักใช้ value semantics ได้ สำหรับ struct ขนาดใหญ่หรือจุดที่ต้องการ mutation ให้ใช้ pointer
// TypeScript — structs/objects always pass by reference// You have no choice; the runtime decidesinterface Config { host: string; port: number; }function connect(cfg: Config) { /* cfg is a reference */ }type Config struct { Host string Port int}
// Value receiver — method gets a copy; cannot modify originalfunc (c Config) String() string { return fmt.Sprintf("%s:%d", c.Host, c.Port)}
// Pointer receiver — method can modify the originalfunc (c *Config) SetPort(p int) { c.Port = p}
func main() { cfg := Config{Host: "localhost", Port: 8080} cfg.SetPort(9090) fmt.Println(cfg.String()) // localhost:9090}package main
import "fmt"
func increment(n *int) { *n++}
func swap(a, b *int) { *a, *b = *b, *a}
func main() { x := 42 fmt.Println("before:", x) increment(&x) fmt.Println("after increment:", x)
a, b := 10, 20 fmt.Printf("before swap: a=%d b=%d\n", a, b) swap(&a, &b) fmt.Printf("after swap: a=%d b=%d\n", a, b)
// Pointer to struct type Point struct{ X, Y int } p := &Point{X: 1, Y: 2} p.X = 99 // Go auto-dereferences: (*p).X = 99 fmt.Println("point:", *p)}Compiling on go.dev (Go 1.27)… offline? an in-browser runtime (~8 MB, Go 1.26) is used instead