Go Academy · Pelajaran

Penerima Penuding pada Kaedah

Mengubah keadaan struct melalui penerima penuding

Pelajaran 3 daripada 414 langkah

Penerima Penuding pada Kaedah ialah pelajaran Go Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Go Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Go Academy merangkumi sejumlah 4 pelajaran.

Ringkasan: Penerima Nilai berbanding Penuding

Penerima nilai beroperasi pada salinan struktur. Penerima penuding beroperasi pada nilai asal. Gunakan penerima penuding apabila kaedah perlu mengubah suai keadaan.

Pengubahan dengan Penerima Penuding

Hanya penerima penuding boleh mengubah suai struktur:

package main
import "fmt"

type Stack struct{ items []int }

func (s *Stack) Push(v int) { s.items = append(s.items, v) }
func (s *Stack) Pop() int {
    n := len(s.items) - 1
    v := s.items[n]
    s.items = s.items[:n]
    return v
}

func main() {
    var st Stack
    st.Push(1); st.Push(2)
    fmt.Println(st.Pop()) // 2
}

Peraturan Keseragaman

Jika mana-mana kaedah pada sesuatu jenis memerlukan penerima penuding, semua kaedah hendaklah menggunakan penerima penuding. Percampuran menyebabkan masalah dengan pemenuhan antara muka:

package main
import "fmt"

type Counter struct{ n int }

func (c *Counter) Inc()   { c.n++ }   // pointer
func (c *Counter) Val() int { return c.n } // pointer too

func main() {
    c := &Counter{}
    c.Inc(); c.Inc()
    fmt.Println(c.Val()) // 2
}

Pemenuhan Antara Muka

Kaedah penerima penuding hanya terdapat dalam set kaedah *T, bukan T. Hal ini mempengaruhi pemenuhan antara muka:

package main
import "fmt"

type Writer interface{ Write([]byte) }

type File struct{ name string }
func (f *File) Write(b []byte) { fmt.Println(string(b)) }

func main() {
    var w Writer = &File{"out.txt"} // OK
    // var w Writer = File{} — compile error
    w.Write([]byte("hello"))
}

Pengambilan Alamat Automatik

Go mengambil alamat secara automatik apabila memanggil kaedah penerima penuding pada nilai yang boleh dialamatkan:

package main
import "fmt"

type Box struct{ V int }
func (b *Box) Double() { b.V *= 2 }

func main() {
    b := Box{5}
    b.Double()          // Go does (&b).Double()
    fmt.Println(b.V)    // 10
}

Nilai yang Tidak Boleh Dialamatkan

Anda tidak boleh memanggil kaedah penerima penuding pada nilai yang tidak boleh dialamatkan (elemen peta dan nilai pemulangan fungsi yang tidak ditugaskan kepada pemboleh ubah):

package main

type T struct{ V int }
func (t *T) Set(v int) { t.V = v }

func getT() T { return T{} }

func main() {
    var t T
    t.Set(1)       // OK — t is addressable
    // getT().Set(1) — ERROR: cannot take address of getT()
    _ = t
}

Penerima Struktur Besar

Sentiasa gunakan penerima penuding untuk struktur besar bagi mengelakkan salinan yang mahal pada setiap panggilan kaedah:

package main

type Image struct{ pixels [1024][1024]uint8 }

// Value receiver copies 1MB per call!
func (img Image) Bad() uint8 { return img.pixels[0][0] }

// Pointer receiver — zero copy
func (img *Image) Good() uint8 { return img.pixels[0][0] }

func main() { _ = Image{} }

Penerima Penuding <code>nil</code>

Kaedah dengan penerima penuding boleh mengendalikan nil dengan selamat:

package main
import "fmt"

type List struct{ head *node }
type node struct{ val int; next *node }

func (l *List) Len() int {
    if l == nil { return 0 }
    count := 0
    for n := l.head; n != nil; n = n.next { count++ }
    return count
}

func main() {
    var l *List
    fmt.Println(l.Len()) // 0
}

Pembenaman dan Penerima Penuding

Apabila membenamkan jenis dengan penerima penuding, struktur luar juga mesti digunakan sebagai penuding untuk mendapatkan kaedah yang dinaikkan:

package main
import "fmt"

type Base struct{ V int }
func (b *Base) Set(v int) { b.V = v }

type Derived struct{ Base }

func main() {
    d := &Derived{}
    d.Set(42)           // promoted pointer-receiver method
    fmt.Println(d.V)    // 42
}

Penyalinan Mutex

Jangan sekali-kali menyalin struktur yang mengandungi sync.Mutex — sentiasa gunakan penerima penuding atau hantar melalui penuding. Menyalin mutex yang dikunci menyebabkan kebuntuan:

package main
import "sync"

type Safe struct {
    mu sync.Mutex
    v  int
}

// Correct: pointer receiver
func (s *Safe) Set(v int) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.v = v
}

func main() { _ = Safe{} }

go vet Mengesan Kesilapan

Jalankan go vet ./... untuk mengesan kesilapan penerima penuding yang biasa, seperti menyalin mutex dan kunci. Ia merupakan sebahagian daripada saluran go build dan semakan CI.

Semakan Pantas

Dalam set kaedah jenis manakah kaedah penerima penuding berada?

Ringkasan

Perkara utama:

  • Penerima penuding mengubah suai; penerima nilai tidak
  • Pastikan semua kaedah pada sesuatu jenis menggunakan jenis penerima yang sama
  • Hanya *T memenuhi antara muka yang memerlukan kaedah penerima penuding
  • Jangan sekali-kali menyalin struktur dengan mutex — gunakan penerima penuding

Arahan Latihan

Laksanakan struktur Queue dengan kaedah penerima penuding Enqueue(int), Dequeue() (int, bool) dan Len() int yang disokong oleh kepingan []int.

Percuma untuk bermula

Pelajari Go dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
51
Pelajaran
203

Soalan Lazim

Adakah pelajaran “Penerima Penuding pada Kaedah” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Go Academy, termasuk “Penerima Penuding pada Kaedah”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Go Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Penerima Penuding pada Kaedah”?

Mengubah keadaan struct melalui penerima penuding Anda berlatih Go Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Go Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Go Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Penerima Penuding pada Kaedah” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Go Academy ini?

Ya. Setiap pelajaran Go Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Apakah Penuding?
  2. Penuding dan Fungsi
  3. Penerima Penuding pada Kaedah
  4. new() dan Bila Perlu Menggunakan Penuding
← Kembali ke Go Academy