A pointer is a variable that stores the memory address of another variable.
package mainimport ( "fmt" "reflect")func main() { var x int = 42 var y int = 50 var p *int = &x // p now holds the address of x fmt.Println("p value: ", reflect.ValueOf(p), "p type: ", reflect.TypeOf(p)) fmt.Println("Value of x:", x, "Address of x:", &x) // 42 fmt.Println("Value of p:", p) // (same memory address) fmt.Println("p:", *p) // dereferencing p *p = 21 // changing the value at the memory address p points to fmt.Println("Value of x after change:", x) // 21 p = &y fmt.Println("p:", *p) // dereferencing p }
Pointers are especially useful with structs, **allowing you to avoid copying large structs and enabling direct modification.**
package mainimport "fmt"// Define a struct called 'Person'type Person struct { Name string Age int}// Function that takes a 'Person' value (copy) and modifies itfunc modifyPersonCopy(p Person) { p.Name = "Alice" p.Age = 30}// Function that takes a pointer to 'Person' and modifies itfunc modifyPersonPointer(p *Person) { p.Name = "Alice" p.Age = 30}func main() { // Original 'Person' struct person := Person{Name: "John", Age: 25} // Copy the struct and attempt modification modifyPersonCopy(person) fmt.Println("After modifyPersonCopy:", person) // No change to 'person' // Pass a pointer to the struct and modify modifyPersonPointer(&person) fmt.Println("After modifyPersonPointer:", person) // Changes to 'person'}
Use pointers to avoid copying large data structures.
Remember that pointers can be nil. Always check for nil pointers before dereferencing them to avoid runtime errors.
// Function that takes a pointer to an integerfunc printValue(val *int) { // Dereference the pointer to access the integer value fmt.Println("Value:", *val) // this line cause runtime Error}func main() { var ptr *int // nil pointer printValue(ptr) // Output: Pointer is nil, cannot dereference.}
Slice copy as the value but the underlying implementation points to the pointer of the array.