Penunjuk, seperti namanya, adalah variabel yang menunjuk ke lokasi di memori sistem Anda tempat suatu nilai disimpan, bukan nilai itu sendiri. Ini adalah alamat ke nilai yang disimpan dalam memori. Definisinya sederhana tetapi konsep ini mungkin sedikit rumit untuk dipahami.

Ketika saya pertama kali mengembangkan pemahaman yang baik tentang pointer di Go, saya bertanya pada diri sendiri, “Bagaimana saya bisa menjelaskan konsep ini kepada anak berusia 5 tahun?” Ya, saya tidak tahu apakah saya dapat menemukan kata-kata untuk menjelaskan hal ini kepada anak berusia 5 tahun, tetapi saya akan tetap berusaha memberi Anda pemahaman yang sederhana dan komprehensif.

Mari kita tuliskan sepotong kecil kode:

package main

import "fmt"

type animal struct {
 name  string
 sound string
}

func main() {
 myAnimal := animal{
   name:  "Cat",
   sound: "Meeeaaawwwwww",
  }
 
 myAnimal.updateAttributes("Cow", "Mooooooooo")

 myAnimal.print("Updated Structure")
}

func (p animal) updateAttributes(newName string, sound string) {
 p.name = newName
 p.sound = sound
}

func (p animal) print(text string) {
 result := fmt.Sprintf("%s ==> %+v \n \n", text, p)
 fmt.Printf("%+v", result)
}

Mari kita uraikan ini:

  1. Kami membuat hewan, cat yang memiliki atribut yang ditentukan dalam tipe animal .
  2. Sekarang, saya ingin memperbarui myAnimal dari cat ke cow. Untuk melakukannya, saya memanggil fungsi penerima saya cat.updateAttributes("cow", "mooooooooo") untuk memperbarui atribut name dan sound .
  3. Akhirnya, saya telah memanggil fungsi penerima lain print untuk mencetak hewan saya yang telah diperbarui.

Mari kita jalankan modul go menggunakan go run .:

//Output:

Updated Structure ==> {
 name:Cat 
 sound:Meeeaaawwwwww 
 zooInfo:{
  town:California 
  email:[email protected] 
  pinCode:12345
 }
}

Wooops…seperti yang kalian lihat, hewanku masih cat.

Saya ingin cow karena saya suka susu.

Mari kita lihat apa yang dicetak di dalam fungsi receiver:

func (p animal) updateAttributes(newName string, sound string) {
 p.name = newName
 p.sound = sound
 
 // Let's call the print command here!
 p.print("Tadaaa")
}

//Output
Tadaaaa ==> {
 name:cow 
 sound:Mooooooooo 
}

Inilah yang terjadi di latar belakang

Singkatnya, Go membuat struct yang benar-benar baru ketika myAnimal diteruskan dari satu fungsi ke fungsi lainnya dan p , argumen fungsi penerima menjadi struct yang baru.

Dengan kata lain, p nilainya disimpan di lokasi memori yang berbeda dari myAnimal .

Untuk melakukan perubahan pada struct asli, kita dapat menggunakan operator * dan &.

Operator '*' dan '&'

Mari kita ubah sedikit fungsi utama dan fungsi penerima updateAttributes:

func main() {
 myAnimal := animal{
   name:  "Cat",
   sound: "Meeeaaawwwwww",
  }

 //STEP#1. Print the original struct myAnimal
 myAnimal.print("Original Structure")
 
 //STEP#2. Create a pointer
 myAnimalPointer := &myAnimal
 
 //STEP#3. myAnimalPointer will still have access
 //to receiver functions of myAnimal.
  //So let's update myAnimalPointer value attributes
 myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")

 //STEP#4. Print the myAnimal values and see if the  
 //original struct values changed
 myAnimal.print("Updated Struct")
}

//STEP#3.1: We'll access the value attributes using * operator 
//and make the changes in the orginal struct value
func (p *animal) updateAttributes(newName string, sound string) {
 (*p).name = newName
 (*p).sound = sound
}

Mari kita bicara tentang fungsi "utama": Pembuatan sebuah pointer

func main() {
 myAnimal := animal{
   name:  "Cat",
   sound: "Meeeaaawwwwww"
  }
  
 myAnimalPointer := &myAnimal
 myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")

//OR We can simply do something like  
(&myAnimal).updateAttributes("Dog", "Woof Woof Woof") //Same thing!
 
 myAnimal.print("Updated Struct")
}

Dengan menggunakan operator &, kita dapat membuat pointer dan kita bisa mendapatkan alamat di memori tempat nilai myAnimal disimpan. Kami telah menetapkan &myAnimal pointer ke variabel myAnimalPointer.

Mari kita bicara tentang fungsi penerima “updateAttributes” : Mengambil nilai dari pointer

func (p *animal) updateAttributes(newName string, sound string) {
 (*p).name = newName
 (*p).sound = sound
}

p adalah penunjuk yang diterima fungsi saat dipanggil.

*animal bukan sebuah pointer melainkan sekadar deskripsi tentang apa yang diharapkan fungsi ini saat dipanggil.

Nilai dalam memori yang direferensikan oleh penunjuk p, dapat diakses menggunakan operator *.

Menggunakan tanda kurung, (*p), akan memberi Anda akses ke atribut struct.

Mari kita jalankan kodenya lagi

go run .

//Output
Original Structure ==> {name:Cat sound:Meeeaaawwwwww}

Updated Struct ==> {name:Dog sound:Woof Woof Woof}

Woohooo 🎉… kami telah memperbarui struct asli myAnimal dengan kekuatan pointer.

Momen Gotcha…

“abracadabra”, biarkan kodenya muncul…

func main() {
 myAnimal := animal{
   name:  "Cat",
   sound: "Meeeaaawwwwww",
  }
 myAnimal.print("Original Structure")
 
 //Let's comment the 2 lines below
 
 //myAnimalPointer := &myAnimal
 //myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")

 //Let's use our same old myAnimal struct without creating a pointer 
 myAnimal.updateAttributes("Dog", "Woof Woof Woof")

 myAnimal.print("Updated Struct")
}

func (p *animal) updateAttributes(newName string, sound string) {
 (*p).name = newName
 (*p).sound = sound
}

Go secara otomatis menangani pembuatan pointer di latar belakang sehingga Anda tidak perlu melakukannya. Dan begitulah, Anda akan mendapatkan hasil yang sama:

go run .

Original Structure ==> {name:Cat sound:Meeeaaawwwwww}

Updated Struct ==> {name:Dog sound:Woof Woof Woof}

Kata Kunci baru

Mari buat pointer menggunakan kata kunci new:

package main

import "fmt"

type animal struct {
 name  string
 sound string
}

func (p *animal) updateAttributes(newName string, sound string) {
 (*p).name = newName
 (*p).sound = sound
}

func main() {
  // LOOK OVER HERE!!!

  myAnimal := new(animal)
  myAnimal.updateAttributes("Dog", "Woof Woof Woof")
  fmt.Printf("%+v", *myAnimal)

}


//Output:
{name:Dog sound:Woof Woof Woof}%

Definisi Resmi:

new mengambil tipe sebagai argumen, mengalokasikan memori yang cukup agar sesuai dengan nilai tipe tersebut dan mengembalikan pointer ke sana.

Saya harap, saya dapat membuat konsep ini sedikit lebih mudah dipahami oleh semua pembaca dan pengikut saya yang terkasih seperti Anda. Jika Anda merasa ada sesuatu yang bisa diperbaiki, silakan berikan komentar dan saya akan memeriksanya.

Semoga harimu indah!

Catatan terima kasih ❤️

Terima kasih sudah mampir. Semoga artikel ini bermanfaat bagi Anda. Kebetulan saya juga punya kebijakan mengikuti balik 😅, jadi tolong ikuti saya di media dan bantu saya mencapai 1 ribu pengikut 🙏🏻. Itu benar-benar akan mendorong saya untuk mengeluarkan lebih banyak konten.

P.S.: Jika Anda merasa ada sesuatu yang bisa diperbaiki atau kurang penjelasannya, kirimkan saya catatan di kotak komentar atau kirimkan saya email ke [email protected]. Lagipula, kamu juga bisa mengajariku satu atau dua hal.