Golang Pointer
Pointer adalah salah satu materi yang cukup membingungkan di Golang. Namun, materi ini sangat penting untuk kita pahami karena pada jika kita membuat project menggunakan Golang, kita akan sering sekali berhadapan dengan yang namanya pointer.
Pointer pada Go adalah tipe data yang menyimpan alamat memori dari suatu variabel. Pointer ditandai dengan tanda * di depan tipe data, misalnya: *int atau *string. Pointer dapat digunakan untuk mengakses dan mengubah nilai dari variabel yang ditunjuk oleh alamat memori tersebut. Pointer juga dapat digunakan untuk passing variabel sebagai referensi ke fungsi atau method.
Secara default, semua variabel di Golang itu menggunakan passing by value, bukan by reference. Artinya, ketika kita mengirimkan sebuah variabel ke dalam function misalnya, maka sebenarnya yang dikirimkan adalan duplikasi dari value-nya.
Berikut ini adalah contoh pointer pada Golang:
package main
import "fmt"
func main() {
// Deklarasi variabel x sebagai integer
x := 5
// Deklarasi pointer p sebagai integer
var p *int
// Memberikan alamat dari x ke pointer p
p = &x
// Menampilkan nilai dari x
fmt.Println("Nilai x:", x)
// Menampilkan alamat memori dari x
fmt.Println("Alamat x:", &x)
// Menampilkan nilai yang ditunjuk oleh pointer p
fmt.Println("Nilai yang ditunjuk oleh p:", *p)
}
output:
Nilai x: 5
Alamat x: 0x1040a124
Nilai yang ditunjuk oleh p: 5
dari contoh diatas, pada kode var p *int
kita mengisi pointer p dengan alamat dari variable x, sehingga p menyimpan alamat memori dari x. Kemudian pada baris terakhir kita mengambil nilai yang ditunjuk oleh pointer p dengan menambahkan tanda * di depan p, sehingga kita akan mendapatkan nilai dari variable x.
Pass by Value
Pass by value adalah sebuah cara untuk passing parameter ke dalam fungsi atau method, dimana nilai dari parameter akan disalin (copy) ke dalam fungsi atau method. Sehingga, jika ada perubahan yang dilakukan pada parameter di dalam fungsi atau method, itu tidak akan mempengaruhi nilai dari parameter asli yang ada di luar fungsi atau method tersebut.
Contoh dari pass by value adalah sebagai berikut:
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
x := 5
y := 3
z := add(x, y)
fmt.Println(z) // output: 8
fmt.Println(x,y) // output: 5 3
}
Di dalam contoh diatas, ketika kita memanggil fungsi add dengan parameter x dan y, maka nilai dari x dan y akan disalin ke dalam fungsi add, sehingga jika ada perubahan yang dilakukan pada x dan y di dalam fungsi add, itu tidak akan mempengaruhi nilai dari x dan y yang ada di luar fungsi add.
Pass by Reference
Pass by reference adalah sebuah cara untuk passing parameter ke dalam fungsi atau method, dimana yang dikirimkan ke dalam fungsi atau method adalah alamat memori dari parameter. Sehingga, jika ada perubahan yang dilakukan pada parameter di dalam fungsi atau method, itu akan mempengaruhi nilai dari parameter asli yang ada di luar fungsi atau method tersebut.
Pada Go, untuk pass by reference menggunakan pointer. Contoh dari pass by reference adalah sebagai berikut:
package main
import "fmt"
func add(x *int, y *int) {
*x = *x + *y
}
func main() {
x := 5
y := 3
add(&x, &y)
fmt.Println(x) // output: 8
}
Di dalam contoh diatas, ketika kita memanggil fungsi add dengan parameter x dan y, maka yang dikirimkan ke dalam fungsi add adalah alamat memori dari x dan y. Sehingga jika ada perubahan yang dilakukan pada x di dalam fungsi add, maka nilai dari x yang ada di luar fungsi add juga akan berubah.
Sebagai catatan, Go tidak memiliki pass by reference secara eksplisit seperti bahasa lain seperti C++ atau Java. Namun, dengan menggunakan pointer, kita dapat mencapai efek yang sama dengan pass by reference.
Operator pada Golang Pointer
Ada beberapa operator yang dapat digunakan untuk pointer pada Go:
- & (address operator) : digunakan untuk mengambil alamat memori dari suatu variabel.
-
- (dereference operator) : digunakan untuk mengambil nilai yang ditunjuk oleh sebuah pointer.
- new : digunakan untuk mengalokasikan memori untuk sebuah variabel dan mengembalikan pointer ke alamat memori yang baru dialokasikan.
- make : digunakan untuk mengalokasikan memori dan menginisialisasi tipe data yang bersifat kompleks seperti slice, map, atau channel.
Contoh penggunaan operator pointer:
package main
import "fmt"
func main() {
x := 5
var p *int = &x // mengambil alamat memori dari x
fmt.Println("Nilai x:", x)
fmt.Println("Nilai yang ditunjuk oleh p:", *p) // mengambil nilai yang ditunjuk oleh p
*p = 10 // mengubah nilai yang ditunjuk oleh p
fmt.Println("Nilai x setelah diubah:", x) // nilai x juga ikut berubah karena menggunakan pass by reference
p1 := new(int) // mengalokasikan memori untuk sebuah int, dan mengembalikan pointer ke alamat memori yang baru dialokasikan
fmt.Println("Nilai yang ditunjuk oleh p1:", *p1) // nilai default int 0
}
Ketika menggunakan operator pointer, kita harus berhati-hati agar tidak mengakses alamat memori yang tidak valid atau tidak diinisialisasi yang dapat menyebabkan crash yang tidak dapat diprediksi.
Pointer Pada Function Parameter
Ketika kita membuat parameter pada sebuah function, secara default parameter tersebut adalah pass by value. Hal ini berarti data akan dicopy setelah itu dikirimkan ke function tersebut. Dengan begitu, ketika kita merubah data dalam sebuah function, maka data aslinya tidak akan berubah.
Terkadang, kita juga ingin membuat sebuah function yang bisa merubah data asli dari parameternya. Untuk melakukannya, kita bisa menggunakan pointer pada parameter functionnya.
Contoh pointer pada function parameter:
package main
import "fmt"
func changeValueToFalse(value *bool) {
*value = false
}
func main() {
value := true
fmt.Println(value) // hasilnya true
changeValueToFalse(&value)
fmt.Println(value) // hasilnya false
}
output:
true
false
Berikutnya: #36: Package dan Import