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

เมธอดบนสตรักต์

ตัวรับค่าเปรียบเทียบกับตัวรับพอยน์เตอร์

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

เมธอดคืออะไร

เมธอดคือฟังก์ชันที่มีอาร์กิวเมนต์รีซีฟเวอร์ รีซีฟเวอร์จะอยู่ระหว่างคีย์เวิร์ด func กับชื่อเมธอด เพื่อผูกฟังก์ชันเข้ากับชนิดข้อมูล

รีซีฟเวอร์แบบค่า

รีซีฟเวอร์แบบค่าจะได้รับสำเนาของสตรักต์ ใช้เมื่อเมธอดไม่จำเป็นต้องแก้ไขสถานะ:

package main
import "fmt"

type Circle struct{ Radius float64 }

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func main() {
    c := Circle{Radius: 5}
    fmt.Printf("%.2f\n", c.Area()) // 78.54
}

รีซีฟเวอร์แบบพอยน์เตอร์

รีซีฟเวอร์แบบพอยน์เตอร์ทำให้เมธอดสามารถแก้ไขสตรักต์ได้ และมีประสิทธิภาพมากกว่าสำหรับสตรักต์ขนาดใหญ่:

package main
import "fmt"

type Counter struct{ N int }

func (c *Counter) Increment() { c.N++ }
func (c *Counter) Reset()     { c.N = 0 }

func main() {
    c := Counter{}
    c.Increment(); c.Increment()
    fmt.Println(c.N) // 2
    c.Reset()
    fmt.Println(c.N) // 0
}

เมื่อใดควรใช้รีซีฟเวอร์แบบพอยน์เตอร์

ใช้รีซีฟเวอร์แบบพอยน์เตอร์เมื่อ:

  • เมธอดจำเป็นต้องแก้ไขรีซีฟเวอร์
  • สตรักต์มีขนาดใหญ่ (ช่วยหลีกเลี่ยงการคัดลอก)
  • ต้องการความสอดคล้อง หากมีเมธอดใดใช้รีซีฟเวอร์แบบพอยน์เตอร์ เมธอดทั้งหมดก็ควรใช้แบบเดียวกัน

ใช้รีซีฟเวอร์แบบค่าเมื่อสตรักต์มีขนาดเล็กและเมธอดอ่านข้อมูลเท่านั้น

นิพจน์เมธอดและค่าจากเมธอด

สามารถใช้เมธอดเป็นค่าแบบชั้นหนึ่งได้:

package main
import "fmt"

type Adder struct{ Base int }

func (a Adder) Add(n int) int { return a.Base + n }

func main() {
    a := Adder{Base: 10}
    fn := a.Add          // method value — bound to a
    fmt.Println(fn(5))   // 15
}

เมธอดบนชนิดข้อมูลที่ไม่ใช่สตรักต์

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

package main
import "fmt"

type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

func main() {
    t := Celsius(100)
    fmt.Println(t.ToFahrenheit()) // 212
}

การแยกอ้างอิงพอยน์เตอร์โดยอัตโนมัติ

Go จะหาที่อยู่หรือแยกอ้างอิงพอยน์เตอร์โดยอัตโนมัติเมื่อเรียกเมธอด คุณจึงไม่จำเป็นต้องเขียน (&c).Method() เอง:

package main
import "fmt"

type Box struct{ Val int }

func (b *Box) Double() { b.Val *= 2 }

func main() {
    b := Box{Val: 5}
    b.Double()           // Go auto-takes address
    fmt.Println(b.Val)   // 10
}

การเชื่อมเมธอดต่อกัน

ส่งคืนพอยน์เตอร์ของรีซีฟเวอร์เพื่อให้สามารถเชื่อมเมธอดต่อกันได้ (รูปแบบตัวสร้าง):

package main
import "fmt"

type Builder struct{ result string }

func (b *Builder) Add(s string) *Builder {
    b.result += s
    return b
}
func (b *Builder) Build() string { return b.result }

func main() {
    s := (&Builder{}).Add("Hello").Add(", ").Add("World").Build()
    fmt.Println(s)
}

เมธอดสตริง (fmt.Stringer)

ใช้เมธอด String() string เพื่อกำหนดวิธีพิมพ์ค่าของชนิดข้อมูล:

package main
import "fmt"

type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}

func main() {
    p := Point{3, 4}
    fmt.Println(p) // (3, 4)
}

รีซีฟเวอร์แบบพอยน์เตอร์ที่เป็น nil

สามารถเรียกเมธอดที่มีรีซีฟเวอร์แบบพอยน์เตอร์ผ่านพอยน์เตอร์ที่เป็น nil ได้ ซึ่งมีประโยชน์สำหรับพฤติกรรมเริ่มต้น:

package main
import "fmt"

type Node struct{ Val int }

func (n *Node) Value() int {
    if n == nil { return 0 }
    return n.Val
}

func main() {
    var n *Node
    fmt.Println(n.Value()) // 0
}

หลักความสอดคล้อง

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

ตรวจสอบความเข้าใจอย่างรวดเร็ว

รีซีฟเวอร์ชนิดใดทำให้เมธอดสามารถแก้ไขฟิลด์ของสตรักต์ได้

สรุป: เมธอด

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

  • เมธอดมีรีซีฟเวอร์อยู่ระหว่าง func กับชื่อเมธอด
  • รีซีฟเวอร์แบบค่า: ใช้อ่านข้อมูลเท่านั้น เหมาะกับสตรักต์ขนาดเล็ก
  • รีซีฟเวอร์แบบพอยน์เตอร์: ใช้แก้ไขข้อมูล เหมาะกับสตรักต์ขนาดใหญ่ และช่วยรักษาความสอดคล้อง
  • Go แยกอ้างอิงพอยน์เตอร์โดยอัตโนมัติ จึงไม่จำเป็นต้องเขียน (&v).Method()
  • ใช้ String() string เพื่อกำหนดการพิมพ์แบบกำหนดเอง

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

กำหนดสตรักต์ BankAccount ที่มีฟิลด์ Balance float64 เพิ่มเมธอดรีซีฟเวอร์แบบพอยน์เตอร์ Deposit และ Withdraw รวมถึงเมธอดรีซีฟเวอร์แบบค่า String()

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

บทเรียน “เมธอดบนสตรักต์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เมธอดบนสตรักต์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. การกำหนดและใช้งานสตรักต์
  2. เมธอดบนสตรักต์
  3. รูปแบบคอนสตรักเตอร์
  4. สตรักต์ไม่ระบุชื่อและการประกอบ
← กลับไปที่ Go Academy