พอยน์เตอร์และฟังก์ชัน
การส่งผ่านค่าเปรียบเทียบกับการส่งผ่านพอยน์เตอร์
พอยน์เตอร์และฟังก์ชัน เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
การส่งผ่านด้วยค่า
Go ส่งอาร์กิวเมนต์ของฟังก์ชันทั้งหมดด้วยค่า ซึ่งหมายความว่าจะมีการสร้างสำเนา การเปลี่ยนแปลงภายในฟังก์ชันจะไม่ส่งผลต่อต้นฉบับ:
package main
import "fmt"
func increment(n int) { n++ }
func main() {
x := 5
increment(x)
fmt.Println(x) // 5 — unchanged
}ส่งผ่านด้วยพอยน์เตอร์
ส่งพอยน์เตอร์เพื่อให้ฟังก์ชันแก้ไขค่าต้นฉบับได้:
package main
import "fmt"
func increment(n *int) { *n++ }
func main() {
x := 5
increment(&x)
fmt.Println(x) // 6
}การคืนค่าพอยน์เตอร์
ฟังก์ชันสามารถคืนค่าพอยน์เตอร์ไปยังค่าที่จัดสรรบนฮีปได้ การวิเคราะห์การหลุดรอดของ Go จะช่วยรับประกันความปลอดภัย:
package main
import "fmt"
func newInt(v int) *int { return &v }
func main() {
p := newInt(42)
fmt.Println(*p) // 42
}ประสิทธิภาพของโครงสร้างขนาดใหญ่
การส่งโครงสร้างขนาดใหญ่ด้วยพอยน์เตอร์ช่วยหลีกเลี่ยงการคัดลอกที่ใช้ทรัพยากรมาก:
package main
import "fmt"
type BigData struct{ Data [1024]int }
func process(d *BigData) { d.Data[0] = 99 }
func main() {
bd := BigData{}
process(&bd)
fmt.Println(bd.Data[0]) // 99
}พอยน์เตอร์ไปยังอินเทอร์เฟซ
แทบไม่จำเป็นต้องใช้ — อินเทอร์เฟซมีพอยน์เตอร์อยู่ภายในแล้ว การส่ง *interface{} มักเป็นสิ่งที่ผิดเกือบทุกครั้ง:
package main
import "fmt"
type Stringer interface{ String() string }
func print(s Stringer) { fmt.Println(s.String()) }
// Pass interface directly, NOT *Stringer
type Name string
func (n Name) String() string { return string(n) }
func main() {
print(Name("Alice"))
}พารามิเตอร์ที่ไม่บังคับด้วยพอยน์เตอร์
ใช้พารามิเตอร์แบบพอยน์เตอร์เพื่อแยกความแตกต่างระหว่าง "ไม่ได้ระบุ" กับค่าศูนย์:
package main
import "fmt"
func greet(name *string) {
if name == nil {
fmt.Println("Hello, stranger")
return
}
fmt.Println("Hello,", *name)
}
func main() {
s := "Alice"
greet(&s)
greet(nil)
}การแก้ไขค่าผ่านสไลซ์
สไลซ์มีพอยน์เตอร์อยู่ภายในแล้ว ดังนั้นโดยมากจึงไม่จำเป็นต้องใช้ *[]T อย่างไรก็ตาม เมื่อ append จัดสรรหน่วยความจำใหม่ คุณจำเป็นต้องใช้พอยน์เตอร์ไปยังสไลซ์นั้นเอง:
package main
import "fmt"
func addItem(s *[]int, v int) { *s = append(*s, v) }
func main() {
nums := []int{1, 2, 3}
addItem(&nums, 4)
fmt.Println(nums) // [1 2 3 4]
}การใช้นามแฝงของพอยน์เตอร์
พอยน์เตอร์หลายตัวที่ชี้ไปยังตัวแปรเดียวกันจะทำให้เกิดการใช้นามแฝง — การเปลี่ยนแปลงผ่านพอยน์เตอร์ตัวหนึ่งจะมองเห็นได้ผ่านพอยน์เตอร์ตัวอื่นทั้งหมด:
package main
import "fmt"
func main() {
x := 10
a, b := &x, &x
*a = 99
fmt.Println(*b) // 99 — same memory
}การหลีกเลี่ยงการใช้พอยน์เตอร์มากเกินไป
ใช้พอยน์เตอร์เมื่อจำเป็นเท่านั้น:
- การแก้ไขค่าภายในฟังก์ชัน
- โครงสร้างขนาดใหญ่ (ตั้งแต่ประมาณ 64 ไบต์ขึ้นไป)
- ใช้ nil เพื่อหมายถึง "ไม่มีค่า"
การใช้พอยน์เตอร์มากเกินไปเพิ่มภาระให้ GC และทำให้โค้ดอ่านเข้าใจได้ยากขึ้น
รูปแบบพอยน์เตอร์ฟังก์ชัน
เก็บพอยน์เตอร์ฟังก์ชันไว้ในแมปสำหรับตารางกระจายงาน:
package main
import "fmt"
func add(a, b int) int { return a + b }
func sub(a, b int) int { return a - b }
func main() {
ops := map[string]func(int,int)int{
"+": add, "-": sub,
}
fmt.Println(ops["+"](10, 3)) // 13
fmt.Println(ops["-"](10, 3)) // 7
}ตรวจสอบอย่างรวดเร็ว
คุณจะทำให้ฟังก์ชันแก้ไขตัวแปรจำนวนเต็มที่กำหนดไว้ในฟังก์ชันผู้เรียกได้อย่างไร
สรุปทบทวน
ประเด็นสำคัญ:
- Go ส่งผ่านค่าด้วยการคัดลอก — ใช้พอยน์เตอร์เมื่อต้องการแก้ไขค่า
- คืนค่าพอยน์เตอร์จากฟังก์ชันสร้างเพื่อจัดสรรบนฮีป
- สไลซ์มีพอยน์เตอร์ภายใน แต่
appendอาจจำเป็นต้องใช้*[]T - หลีกเลี่ยงการใช้พอยน์เตอร์มากเกินไป — เลือกใช้ค่าแทนสำหรับชนิดข้อมูลขนาดเล็ก
โจทย์ฝึกปฏิบัติ
เขียนฟังก์ชัน normalize ที่รับ *[]string และแปลงสตริงทั้งหมดเป็นตัวพิมพ์เล็กภายในสไลซ์เดิม โดยใช้ strings.ToLower
คำถามที่พบบ่อย
บทเรียน “พอยน์เตอร์และฟังก์ชัน” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พอยน์เตอร์และฟังก์ชัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พอยน์เตอร์และฟังก์ชัน”
การส่งผ่านค่าเปรียบเทียบกับการส่งผ่านพอยน์เตอร์ คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “พอยน์เตอร์และฟังก์ชัน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พอยน์เตอร์คืออะไร
- พอยน์เตอร์และฟังก์ชัน
- ตัวรับพอยน์เตอร์ในเมธอด
- new() และกรณีที่ควรใช้พอยน์เตอร์