Pass by Value vs Reference
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 21 dari 107.
Go adalah bahasa pass-by-value. Saat kamu meneruskan variabel ke fungsi, Go membuat salinan nilainya. Artinya, perubahan di dalam fungsi tidak memengaruhi variabel aslinya.
func double(n int) {
n = n * 2
}
func main() {
x := 10
double(x)
fmt.Println(x) // 10 (tidak berubah)
}Hal yang sama berlaku untuk struct. Mengirim struct ke fungsi akan menyalin semua field-nya, sehingga perubahan di dalam fungsi akan hilang.
type Person struct {
Name string
Age int
}
func birthday(p Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(alice)
fmt.Println(alice.Age) // 30 (tidak berubah)
}Untuk mengubah nilai asli, berikan pointer. Pointer itu sendiri disalin, tetapi tetap menunjuk ke alamat memori yang sama sehingga kamu dapat mengubah data asli.
func birthday(p *Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(&alice)
fmt.Println(alice.Age) // 31 (diubah!)
}Gunakan pointer saat kamu perlu mengubah nilai asli atau saat mengirim struct berukuran besar agar tidak perlu menyalin data dengan biaya tinggi. Gunakan nilai saat kamu ingin melindungi data asli dari perubahan yang tidak disengaja.
Tantangan
MudahMari buat sistem keranjang belanja yang menunjukkan perbedaan antara meneruskan struct berdasarkan nilai dan berdasarkan pointer. Kamu akan melihat langsung bahwa hanya parameter pointer yang dapat mengubah data asli.
Kamu akan menyusun kodemu dalam dua file:
cart.go: Definisikan structCartItemdengan fieldName(string),Price(float64), danQuantity(int). Buat dua fungsi yang mencoba memperbarui kuantitas:UpdateQuantityByValuemenerimaCartItem(berdasarkan nilai) dan kuantitas baru, lalu menetapkan kuantitas item ke nilai baruUpdateQuantityByPointermenerima*CartItem(pointer) dan kuantitas baru, lalu menetapkan kuantitas item ke nilai baru
TotalpadaCartItemyang mengembalikan harga dikalikan kuantitas.main.go: Baca detail item dari input, buat CartItem, lalu tunjukkan kedua pendekatan pembaruan. Pertama, coba perbarui dengan fungsi berdasarkan nilai dan tampilkan hasilnya, lalu perbarui dengan fungsi pointer dan tampilkan hasilnya lagi.
Input berikut akan diberikan:
- Baris 1: Nama item
- Baris 2: Harga (float)
- Baris 3: Kuantitas awal (integer)
- Baris 4: Kuantitas baru yang akan ditetapkan (integer)
Format output:
Initial: [Name] x[Quantity] = $[Total]
After value update: [Name] x[Quantity] = $[Total]
After pointer update: [Name] x[Quantity] = $[Total]Misalnya, jika diberikan Laptop, 999.99, 1, dan 3, outputmu seharusnya:
Initial: Laptop x1 = $999.99
After value update: Laptop x1 = $999.99
After pointer update: Laptop x3 = $2999.97Perhatikan bahwa kuantitas tetap 1 setelah pembaruan berdasarkan nilai (fungsi mengubah salinan), tetapi berubah menjadi 3 setelah pembaruan pointer (fungsi mengubah data asli). Tampilkan total dengan dua angka di belakang koma.
Coba sendiri
package main
import (
"fmt"
)
func main() {
// Baca input
var name string
var price float64
var initialQty, newQty int
fmt.Scanln(&name)
fmt.Scanln(&price)
fmt.Scanln(&initialQty)
fmt.Scanln(&newQty)
// TODO: Buat CartItem dengan nilai input
// TODO: Tampilkan keadaan awal dengan format:
// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)
// TODO: Coba perbarui jumlah menggunakan UpdateQuantityByValue
// Lalu tampilkan hasilnya (perhatikan bahwa jumlahnya tidak berubah)
// TODO: Perbarui jumlah menggunakan UpdateQuantityByPointer
// Lalu tampilkan hasilnya (perhatikan bahwa jumlahnya berubah)
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online