0Pricing
Go Academy · บทเรียน

new() และกรณีที่ควรใช้พอยน์เตอร์

การจัดสรรด้วย new และรูปแบบการใช้พอยน์เตอร์ที่พบบ่อย

new() และกรณีที่ควรใช้พอยน์เตอร์ เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

ฟังก์ชันในตัว new()

new(T) จัดสรรค่า T ที่ถูกกำหนดเป็นศูนย์ทั้งหมดและคืนค่าเป็น *T สำหรับโครงสร้าง จะเทียบเท่ากับ &T{}:

package main
import "fmt"

func main() {
    p := new(int)
    fmt.Println(*p)     // 0
    *p = 42
    fmt.Println(*p)     // 42

    type Point struct{ X, Y int }
    pt := new(Point)
    fmt.Println(*pt)    // {0 0}
}

new กับ &T{}

สำหรับโครงสร้าง &T{} เป็นรูปแบบที่สอดคล้องกับแนวทางของ Go มากกว่า และอนุญาตให้กำหนดค่าเริ่มต้นให้ฟิลด์ได้ โดยทั่วไป Go สมัยใหม่แทบไม่ใช้ new:

package main
import "fmt"

type Config struct{ Port int; Host string }

func main() {
    a := new(Config)          // zeroed
    b := &Config{Port: 8080}  // initialized
    fmt.Println(a, b)
}

เมื่อใดควรคืนค่าพอยน์เตอร์

คืนค่าพอยน์เตอร์จากฟังก์ชันสร้างเมื่อ:

  • โครงสร้างมีสถานะและผู้เรียกต้องใช้ข้อมูลอินสแตนซ์เดียวกันร่วมกัน
  • โครงสร้างมีเมธอดแบบรีซีฟเวอร์พอยน์เตอร์ ซึ่งจำเป็นต่อการรองรับอินเทอร์เฟซ
  • โครงสร้างมีขนาดใหญ่และการคัดลอกจะใช้ทรัพยากรมาก

เมื่อใดควรคืนค่า

คืนค่าเมื่อ:

  • ชนิดข้อมูลมีขนาดเล็ก มีเพียงไม่กี่ฟิลด์
  • เป็นการกำหนดค่าที่ไม่เปลี่ยนแปลง
  • ต้องการให้ชัดเจนว่าผู้เรียกจะได้รับสำเนาที่เป็นอิสระจากกัน

ตัวอย่างเช่น time.Time จะถูกคืนค่าโดยตรง แม้ว่าจะมีเมธอดจำนวนมาก

พอยน์เตอร์ในสไลซ์และแมป

การเก็บพอยน์เตอร์ไว้ในชุดข้อมูลทำให้สามารถใช้การแก้ไขค่าร่วมกันได้:

package main
import "fmt"

type User struct{ Name string; Score int }

func main() {
    users := []*User{{"Alice", 0}, {"Bob", 0}}
    users[0].Score = 100
    fmt.Println(users[0]) // &{Alice 100}
}

พอยน์เตอร์ไปยังชนิดพื้นฐานเพื่อรองรับค่าที่ไม่บังคับ

ฟิลด์ชนิด *int หรือ *string สามารถเป็น nil เพื่อหมายถึง "ยังไม่ได้กำหนดค่า" ซึ่งมีประโยชน์สำหรับ JSON ที่ใช้ omitempty หรือคอลัมน์ฐานข้อมูลที่ไม่บังคับ:

package main
import "fmt"

type Profile struct {
    Name string
    Age  *int // nil means not provided
}

func main() {
    p := Profile{Name: "Alice"}
    fmt.Println(p.Age == nil) // true
    age := 30
    p.Age = &age
    fmt.Println(*p.Age) // 30
}

การหลีกเลี่ยงการใช้พอยน์เตอร์พร่ำเพรื่อ

การใช้พอยน์เตอร์มากเกินไปเพิ่มภาระให้ GC และลดความเป็นท้องถิ่นของแคช ควรทำการวัดประสิทธิภาพก่อนเปลี่ยนชนิดข้อมูลแบบค่าเป็นพอยน์เตอร์เพียงเพราะเหตุผลด้านประสิทธิภาพ

make กับ new

make เริ่มต้นการทำงานของสไลซ์ แมป และแชนเนล เพราะชนิดข้อมูลเหล่านี้ต้องมีการตั้งค่าภายใน ส่วน new จัดสรรหน่วยความจำที่กำหนดเป็นศูนย์ให้กับชนิดข้อมูลใดก็ได้และคืนค่าพอยน์เตอร์ ทั้งสองอย่างมีจุดประสงค์ต่างกัน:

package main
import "fmt"

func main() {
    s := make([]int, 5)           // usable slice
    m := make(map[string]int)     // usable map
    p := new(int)                 // *int pointing to 0
    fmt.Println(s, m, *p)
}

รูปแบบพอยน์เตอร์ที่ไม่เปลี่ยนแปลง

คืนค่า *T แต่ระบุไว้ในเอกสารว่าเป็นค่าที่ไม่เปลี่ยนแปลง ผู้ใช้ไม่ควรแก้ไขค่า รูปแบบนี้พบได้ทั่วไปในออบเจ็กต์การกำหนดค่าที่ใช้ร่วมกันระหว่างกอร์รูทีน

สรุปความปลอดภัยของพอยน์เตอร์

กฎเพื่อความปลอดภัยเมื่อใช้พอยน์เตอร์:

  • ตรวจสอบ nil ก่อนยกเลิกการอ้างอิงเสมอ
  • อย่าเก็บพอยน์เตอร์ไปยังตัวแปรบนสแต็กไว้นานกว่าอายุการใช้งานของตัวแปรนั้น การวิเคราะห์การหลุดรอดของ Go จะจัดการเรื่องนี้ให้
  • อย่าแปลงชนิดของ unsafe.Pointer เว้นแต่จำเป็นอย่างยิ่ง
  • ให้คอมไพเลอร์จัดการการเลือกใช้สแต็กหรือฮีป

ตรวจสอบอย่างรวดเร็ว

new(int) คืนค่าอะไร

สรุปทบทวน: new และพอยน์เตอร์

ประเด็นสำคัญ:

  • new(T) คืนค่า *T ที่ถูกกำหนดเป็นศูนย์ — ไม่ค่อยใช้ ควรเลือก &T{}
  • คืนค่าเมื่อข้อมูลมีขนาดเล็กหรือไม่เปลี่ยนแปลง ใช้พอยน์เตอร์เมื่อข้อมูลมีสถานะหรือมีขนาดใหญ่
  • ฟิลด์ชนิด *T ทำให้ใช้ nil เพื่อสื่อว่าไม่มีค่าได้
  • อย่าใช้พอยน์เตอร์มากเกินไป — GC มีต้นทุน

โจทย์ฝึกปฏิบัติ

สร้างโครงสร้าง Settings ที่มีฟิลด์ชนิด *int สำหรับ MaxConnections เขียนฟังก์ชันที่รับ *Settings และกำหนดค่าเริ่มต้นเฉพาะเมื่อฟิลด์เป็น nil

คำถามที่พบบ่อย

บทเรียน “new() และกรณีที่ควรใช้พอยน์เตอร์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “new() และกรณีที่ควรใช้พอยน์เตอร์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “new() และกรณีที่ควรใช้พอยน์เตอร์”

การจัดสรรด้วย new และรูปแบบการใช้พอยน์เตอร์ที่พบบ่อย คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “new() และกรณีที่ควรใช้พอยน์เตอร์” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม

ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พอยน์เตอร์คืออะไร
  2. พอยน์เตอร์และฟังก์ชัน
  3. ตัวรับพอยน์เตอร์ในเมธอด
  4. new() และกรณีที่ควรใช้พอยน์เตอร์
← กลับไปที่ Go Academy