A pointer is a variable that stores the memory address of another variable. Instead of holding a direct value, it holds a reference to a value stored elsewhere in memory.
đ Pointers are used for efficient memory management and allow modifying variables indirectly by passing their address instead of a copy.
In Go, a pointer is declared using the *
(asterisk) symbol.
var ptr *int // Declares a pointer to an integer
By default, an uninitialized pointer has a zero value of nil
, meaning it doesnât point to any valid memory address.
package main
import "fmt"
func main() {
var ptr *int // Declaring a pointer
fmt.Println("Pointer value:", ptr) // nil (default value)
}
đš Output:
Pointer value: <nil>
&
Operator)The address-of operator (&
) is used to get the memory address of a variable.
package main
import "fmt"
func main() {
num := 42
ptr := &num // Getting the memory address of num
fmt.Println("Value of num:", num)
fmt.Println("Address of num:", ptr) // Pointer holds the memory address
}
đš Output:
Value of num: 42
Address of num: 0xc000014080 // (example memory address)
đ &num
returns the memory address of num
, which is stored in ptr
.
*
Operator)The dereference operator (*
) is used to access the value stored at a pointerâs address.
package main
import "fmt"
func main() {
num := 42
ptr := &num // Pointer to num
fmt.Println("Pointer address:", ptr)
fmt.Println("Value at pointer address:", *ptr) // Dereferencing pointer
}
đš Output:
Pointer address: 0xc000014080 // (example memory address)
Value at pointer address: 42
đ *ptr
dereferences the pointer and retrieves the value stored at that address.
Pointers allow modifying the original value by dereferencing them.
package main
import "fmt"
func main() {
num := 10
ptr := &num // Pointer to num
*ptr = 20 // Modifying the original value through the pointer
fmt.Println("Updated num:", num) // num is now 20
}
đš Output:
Updated num: 20
đ Since ptr
points to num
, modifying *ptr
changes the original variableâs value.
Passing a pointer to a function allows modifying the original variable instead of a copy.
package main
import "fmt"
// Function that modifies the value using a pointer
func updateValue(ptr *int) {
*ptr = *ptr + 5 // Dereferencing and modifying value
}
func main() {
num := 10
updateValue(&num) // Passing address of num
fmt.Println("Updated num:", num) // num is modified
}
đš Output:
Updated num: 15
đ Here, updateValue
receives a pointer and modifies the original value by dereferencing it.
A pointer can store the address of another pointer.
package main
import "fmt"
func main() {
num := 50
ptr := &num // Pointer to num
pptr := &ptr // Pointer to pointer
fmt.Println("Value of num:", num)
fmt.Println("Pointer to num:", ptr)
fmt.Println("Pointer to pointer:", pptr)
fmt.Println("Value using double pointer:", **pptr) // Dereferencing twice
}
đš Output:
Value of num: 50
Pointer to num: 0xc000014080
Pointer to pointer: 0xc000006028
Value using double pointer: 50
đ pptr
stores the address of ptr
, and **pptr
retrieves the original value (num
).
Pointers are commonly used with structs to modify their fields efficiently.
package main
import "fmt"
type Person struct {
name string
age int
}
func updateAge(p *Person) {
p.age = p.age + 1 // Modifying struct field via pointer
}
func main() {
p1 := Person{"Alice", 25}
updateAge(&p1) // Passing struct pointer
fmt.Println("Updated Age:", p1.age)
}
đš Output:
Updated Age: 26
đ Since p
is a pointer to Person
, modifying p.age
updates p1.age
.
new()
new()
allocates memory for a single variable and returns a pointer.
package main
import "fmt"
func main() {
ptr := new(int) // Allocating memory for an integer
*ptr = 100
fmt.Println("Value at ptr:", *ptr)
}
đš Output:
Value at ptr: 100
đ new(int)
allocates memory for an integer and returns a pointer to it.
make()
make()
is used for slices, maps, and channels, as it initializes internal structures.
package main
import "fmt"
func main() {
myMap := make(map[string]int) // Allocates and initializes map
myMap["age"] = 30
fmt.Println(myMap)
}
đš Output:
map[age:30]
đ make()
initializes a map (or slice/channel), whereas new()
only allocates memory.
A nil pointer is an uninitialized pointer and causes runtime errors if dereferenced.
package main
import "fmt"
func main() {
var ptr *int // Nil pointer (uninitialized)
if ptr == nil {
fmt.Println("Pointer is nil, avoiding dereferencing.")
} else {
fmt.Println(*ptr) // Error if dereferenced
}
}
đš Output:
Pointer is nil, avoiding dereferencing.
đ Always check for nil
before dereferencing a pointer to avoid runtime errors.
Feature | Description |
---|---|
Pointer Declaration | var ptr *int |
Get Address (& ) | ptr = &num |
Dereference (* ) | value := *ptr |
Modify Value | *ptr = newValue |
Pass to Function | func update(ptr *int) |
Pointer to Pointer | pptr := &ptr , **pptr |
Struct Pointer | func modify(p *Person) |
New vs. Make | new() (memory allocation), make() (slice/map/channel init) |
đ Pointers in Go improve efficiency, reduce memory overhead, and allow modifying original data without copying! đ
Pointer āĻāĻāĻāĻŋ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞ āϝāĻž āĻ āύā§āϝ āĻāĻāĻāĻŋ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞ āĻāϰ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž āϧāϰ⧠āϰāĻžāĻā§āĨ¤ āϏāϰāĻžāϏāϰāĻŋ āĻāĻāĻāĻŋ āĻŽāĻžāύ āϧāϰ⧠āϰāĻžāĻāĻžāϰ āĻĒāϰāĻŋāĻŦāϰā§āϤā§, āĻāĻāĻŋ āĻŽā§āĻŽā§āϰāĻŋāϰ āĻ āύā§āϝ āĻā§āĻĨāĻžāĻ āĻĨāĻžāĻāĻž āĻāĻāĻāĻŋ āĻŽāĻžāύā§āϰ āϰā§āĻĢāĻžāϰā§āύā§āϏ āϧāϰ⧠āϰāĻžāĻā§āĨ¤
đ Pointers āĻā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧ?
Go-āϤā§, Pointer āĻā§āώāĻŖāĻž āĻāϰāϤ⧠* (āĻ ā§āϝāĻžāϏā§āĻā§āϰāĻŋāϏā§āĻ) āĻāĻŋāĻšā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧāĨ¤
var ptr *int // āĻāĻāĻāĻŋ integer āĻāϰ āĻāύā§āϝ pointer āĻā§āώāĻŖāĻž āĻāϰāĻž āĻšāĻā§āĻā§
āĻĄāĻŋāĻĢāϞā§āĻāĻāĻžāĻŦā§, āĻāĻāĻāĻŋ uninitialized pointer-āĻāϰ āĻŽāĻžāύ āĻšāϝāĻŧ nil, āĻ āϰā§āĻĨāĻžā§ āĻāĻāĻŋ āĻā§āύāĻ āĻŦā§āϧ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āύāĻŋāϰā§āĻĻā§āĻļ āĻāϰ⧠āύāĻžāĨ¤
package main
import "fmt"
func main() {
var ptr *int // Pointer āĻā§āώāĻŖāĻž āĻāϰāĻž āĻšāĻā§āĻā§
fmt.Println("Pointer āĻŽāĻžāύ:", ptr) // nil (āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύ)
}
Pointer āĻŽāĻžāύ: <nil>
Address-of āĻ āĻĒāĻžāϰā§āĻāϰ (&) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻā§āύ⧠āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞā§āϰ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤
package main
import "fmt"
func main() {
num := 42
ptr := &num // num-āĻāϰ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāĻā§āĻā§
fmt.Println("num-āĻāϰ āĻŽāĻžāύ:", num)
fmt.Println("num-āĻāϰ āĻ āĻŋāĻāĻžāύāĻž:", ptr) // Pointer āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž āϧāϰ⧠āϰāĻžāĻāĻā§
}
num-āĻāϰ āĻŽāĻžāύ: 42
num-āĻāϰ āĻ āĻŋāĻāĻžāύāĻž: 0xc000014080 // (āĻāĻĻāĻžāĻšāϰāĻŖāϏā§āĻŦāϰā§āĻĒ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž)
đ &num num-āĻāϰ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž āĻĢā§āϰāϤ āĻĻā§āϝāĻŧ, āϝāĻž ptr-āĻ āϏāĻāϰāĻā§āώāĻŋāϤ āĻšāϝāĻŧāĨ¤
Dereference āĻ āĻĒāĻžāϰā§āĻāϰ (*) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠pointer-āĻāϰ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻĨāĻžāĻāĻž āĻŽāĻžāύāĻāĻŋ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤
package main
import "fmt"
func main() {
num := 42
ptr := &num // num-āĻāϰ Pointer
fmt.Println("Pointer āĻ āĻŋāĻāĻžāύāĻž:", ptr)
fmt.Println("Pointer-āĻāϰ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻĨāĻžāĻāĻž āĻŽāĻžāύ:", *ptr) // Pointer dereference āĻāϰ⧠āĻŽāĻžāύ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāĻā§āĻā§
}
Pointer āĻ āĻŋāĻāĻžāύāĻž: 0xc000014080 // (āĻāĻĻāĻžāĻšāϰāĻŖāϏā§āĻŦāϰā§āĻĒ āĻŽā§āĻŽā§āϰāĻŋ āĻ āĻŋāĻāĻžāύāĻž)
Pointer-āĻāϰ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻĨāĻžāĻāĻž āĻŽāĻžāύ: 42
đ *ptr Pointer dereference āĻāϰ⧠āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻĨāĻžāĻāĻž āĻāϏāϞ āĻŽāĻžāύāĻāĻŋ āĻĢā§āϰāϤ āĻĻā§āϝāĻŧāĨ¤
Pointer āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŽā§āϞ āĻŽāĻžāύāĻāĻŋ dereference āĻāϰ⧠āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āϝāĻžāϝāĻŧāĨ¤
package main
import "fmt"
func main() {
num := 10
ptr := &num // num-āĻāϰ Pointer
*ptr = 20 // Pointer āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻŽā§āϞ āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āĻšāĻā§āĻā§
fmt.Println("āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ num:", num) // num-āĻāϰ āĻŽāĻžāύ āĻāĻāύ 20
}
āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ num: 20
đ āϝā§āĻšā§āϤ⧠ptr num-āĻāϰ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āύāĻŋāϰā§āĻĻā§āĻļ āĻāϰāĻā§, āϤāĻžāĻ *ptr āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϞ⧠āĻŽā§āϞ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞ num-āĻāϰ āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāĻŋāϤ āĻšāϝāĻŧāĨ¤
Pointer function-āĻ pass āĻāϰāϞ⧠āĻŽā§āϞ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞāĻāĻŋ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āϝāĻžāϝāĻŧ, āĻŽāĻžāύā§āϰ āĻāĻĒāĻŋ āύāϝāĻŧāĨ¤
package main
import "fmt"
// Pointer āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻžāϰ āĻĢāĻžāĻāĻļāύ
func updateValue(ptr *int) {
*ptr = *ptr + 5 // Dereference āĻāϰ⧠āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āĻšāĻā§āĻā§
}
func main() {
num := 10
updateValue(&num) // num-āĻāϰ āĻ āĻŋāĻāĻžāύāĻž pass āĻāϰāĻž āĻšāĻā§āĻā§
fmt.Println("āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ num:", num) // num-āĻāϰ āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāĻŋāϤ āĻšāϝāĻŧā§āĻā§
}
āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ num: 15
đ āĻāĻāĻžāύā§, updateValue āĻāĻāĻāĻŋ Pointer āĻā§āϰāĻšāĻŖ āĻāϰ⧠āĻāĻŦāĻ dereference āĻāϰ⧠āĻŽā§āϞ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞā§āϰ āĻŽāĻžāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰā§āĨ¤
āĻāĻāĻāĻŋ Pointer āĻāϰā§āĻāĻāĻŋ Pointer-āĻāϰ āĻ āĻŋāĻāĻžāύāĻž āϧāĻžāϰāĻŖ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
package main
import "fmt"
func main() {
num := 50
ptr := &num // num-āĻāϰ Pointer
pptr := &ptr // Pointer-āĻāϰ Pointer
fmt.Println("num-āĻāϰ āĻŽāĻžāύ:", num)
fmt.Println("num-āĻāϰ Pointer:", ptr)
fmt.Println("Pointer-āĻāϰ Pointer:", pptr)
fmt.Println("Double Pointer āĻĻāĻŋāϝāĻŧā§ āĻŽāĻžāύ:", **pptr) // āĻĻā§āĻāĻŦāĻžāϰ dereference āĻāϰ⧠āĻŽā§āϞ āĻŽāĻžāύ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāĻā§āĻā§
}
num-āĻāϰ āĻŽāĻžāύ: 50
num-āĻāϰ Pointer: 0xc000014080
Pointer-āĻāϰ Pointer: 0xc000006028
Double Pointer āĻĻāĻŋāϝāĻŧā§ āĻŽāĻžāύ: 50
đ pptr ptr-āĻāϰ āĻ āĻŋāĻāĻžāύāĻž āϧāϰ⧠āϰāĻžāĻā§, āĻāĻŦāĻ **pptr dereference āĻāϰ⧠āĻŽā§āϞ āĻŽāĻžāύāĻāĻŋ (num) āĻĢā§āϰāϤ āĻĻā§āϝāĻŧāĨ¤
Pointer-āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ structs-āĻāϰ āĻĢāĻŋāϞā§āĻĄāĻā§āϞ⧠āĻāĻžāϰā§āϝāĻāϰāĻāĻžāĻŦā§ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āϝāĻžāϝāĻŧāĨ¤
package main
import "fmt"
type Person struct {
name string
age int
}
func updateAge(p *Person) {
p.age = p.age + 1 // Pointer-āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ struct āĻĢāĻŋāϞā§āĻĄ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻž āĻšāĻā§āĻā§
}
func main() {
p1 := Person{"Alice", 25}
updateAge(&p1) // struct-āĻāϰ Pointer pass āĻāϰāĻž āĻšāĻā§āĻā§
fmt.Println("āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ āĻŦāϝāĻŧāϏ:", p1.age)
}
āĻšāĻžāϞāύāĻžāĻāĻžāĻĻāĻā§āϤ āĻŦāϝāĻŧāϏ: 26
đ āϝā§āĻšā§āϤ⧠p Person-āĻāϰ Pointer, āϤāĻžāĻ p.age āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϞ⧠āĻŽā§āϞ struct p1-āĻāϰ age āĻĢāĻŋāϞā§āĻĄ āĻāĻĒāĻĄā§āĻ āĻšāϝāĻŧāĨ¤
new()
āĻāĻāĻāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞā§āϰ āĻāύā§āϝ āĻŽā§āĻŽā§āϰāĻŋ āĻŦāϰāĻžāĻĻā§āĻĻ āĻāϰ⧠āĻāĻŦāĻ āĻāĻāĻāĻŋ Pointer āĻĢā§āϰāϤ āĻĻā§āϝāĻŧāĨ¤
package main
import "fmt"
func main() {
ptr := new(int) // āĻāĻāĻāĻŋ integer-āĻāϰ āĻāύā§āϝ āĻŽā§āĻŽā§āϰāĻŋ āĻŦāϰāĻžāĻĻā§āĻĻ āĻāϰāĻž āĻšāĻā§āĻā§
*ptr = 100
fmt.Println("Pointer-āĻāϰ āĻŽāĻžāύ:", *ptr)
}
Pointer-āĻāϰ āĻŽāĻžāύ: 100
đ new(int)
āĻāĻāĻāĻŋ integer-āĻāϰ āĻāύā§āϝ āĻŽā§āĻŽā§āϰāĻŋ āĻŦāϰāĻžāĻĻā§āĻĻ āĻāϰ⧠āĻāĻŦāĻ āϤāĻžāϰ Pointer āĻĢā§āϰāϤ āĻĻā§āϝāĻŧāĨ¤
make()
slice, map āĻāĻŦāĻ channel-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻŦāĻšā§āϤ āĻšāϝāĻŧ āĻāĻŦāĻ āĻāĻā§āϞā§āĻā§ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻāĻāĻžāĻŦā§ initialize āĻāϰā§āĨ¤
package main
import "fmt"
func main() {
myMap := make(map[string]int) // āĻāĻāĻāĻŋ map allocate āĻāĻŦāĻ initialize āĻāϰāĻž āĻšāĻā§āĻā§
myMap["age"] = 30
fmt.Println(myMap)
}
map[age:30]
đ make()
map (āĻŦāĻž slice/channel) initialize āĻāϰā§, āĻāĻŋāύā§āϤ⧠new()
āĻļā§āϧ⧠āĻŽā§āĻŽā§āϰāĻŋ āĻŦāϰāĻžāĻĻā§āĻĻ āĻāϰā§āĨ¤
Nil pointer āĻšāϞ⧠āĻāĻāĻāĻŋ uninitialized pointer āĻāĻŦāĻ āĻāĻāĻžāĻā§ dereference āĻāϰāϞ⧠runtime āϤā§āϰā§āĻāĻŋ āĻāĻā§āĨ¤
package main
import "fmt"
func main() {
var ptr *int // Nil pointer (uninitialized)
if ptr == nil {
fmt.Println("Pointer āĻāĻŋ nil, dereferencing āĻāĻĄāĻŧāĻžāύ⧠āĻšāĻā§āĻā§āĨ¤")
} else {
fmt.Println(*ptr) // dereference āĻāϰāϞ⧠āϤā§āϰā§āĻāĻŋ āĻāĻāĻŦā§
}
}
Pointer āĻāĻŋ nil, dereferencing āĻāĻĄāĻŧāĻžāύ⧠āĻšāĻā§āĻā§āĨ¤
đ Dereference āĻāϰāĻžāϰ āĻāĻā§ pointer āĻāĻŋ nil āĻāĻŋāύāĻž āϤāĻž āϏāĻŦāϏāĻŽāϝāĻŧ āĻā§āĻ āĻāϰāĻž āĻāĻāĻŋāϤ runtime āϤā§āϰā§āĻāĻŋ āĻāĻĄāĻŧāĻžāϤā§āĨ¤
āĻāĻāĻžāĻŦā§āĻ Pointers āĻŦā§āϝāĻŦāĻšāĻžāϰā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻāĻŽāϰāĻž āĻāĻžāϰā§āϝāĻāϰāĻāĻžāĻŦā§ āĻŽā§āĻŽā§āϰāĻŋ āĻŦā§āϝāĻŦāϏā§āĻĨāĻžāĻĒāύāĻž āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ āĻāĻŦāĻ āĻŽā§āϞ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞāĻā§āϞā§āĻā§ āϏāϰāĻžāϏāϰāĻŋ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ! đ