Pointers have a special value called nil, which represents the absence of a value. While nil is useful for indicating that something doesn't exist, it can also cause your program to crash if not handled properly.
nil is Go's way of representing "nothing" or "no value". It's the zero value (default value) for pointers:
var name *string
fmt.Println(name) // Output: <nil>
var age *int
fmt.Println(age) // Output: <nil>
When you declare a pointer variable without initializing it, it automatically has the value nil.
Trying to access or modify a value through a nil pointer will cause your program to panic (crash):
type Fighter struct {
Name string
PowerLevel int
}
func main() {
var fighter *Fighter // fighter is nil
fmt.Println(fighter.Name) // PANIC! Cannot access fields of nil pointer
}
This is called a "nil pointer dereference" and it's one of the most common runtime errors.
Before using a pointer, you should check if it's nil:
type Fighter struct {
Name string
PowerLevel int
}
func main() {
var fighter *Fighter
if fighter != nil {
fmt.Println(fighter.Name)
} else {
fmt.Println("Fighter is nil!")
}
}
// Output: Fighter is nil!
A "nil guard" is a defensive check at the beginning of a function to ensure a pointer isn't nil:
type Fighter struct {
Name string
PowerLevel int
}
func displayStats(fighter *Fighter) {
if fighter == nil {
fmt.Println("No fighter to display")
return
}
fmt.Println(fighter.Name, "has power level", fighter.PowerLevel)
}
func main() {
var goku *Fighter
displayStats(goku) // Output: No fighter to display
vegeta := &Fighter{Name: "Vegeta" PowerLevel
Functions can also return values based on nil checks:
type Fighter struct {
Name string
PowerLevel int
}
func getPowerLevel(fighter *Fighter) int {
if fighter == nil {
return 0 // Return default value for nil
}
return fighter.PowerLevel
}
func main() {
var unknown *Fighter
fmt.Println("Power:", getPowerLevel(unknown)) // Output: Power: 0
goku := &Fighter{Name: "Goku", PowerLevel: 9000}
fmt goku
nil can be useful to indicate that a value might not exist:
type Fighter struct {
Name string
PowerLevel int
}
func findFighter(name string) *Fighter {
if name == "Goku" {
return &Fighter{Name: "Goku", PowerLevel: 9000}
}
return nil // Fighter not found
}
func main() {
fighter := findFighter("Goku")
if fighter != nil {
fmt.Println("Found:", fighter.Name)
When working with pointers, you can use the * operator to dereference (access the value):
type Item struct {
Name string
Value int
}
func getValue(item *Item) int {
if item == nil {
return 0
}
// Both work the same for struct fields:
return item.Value // Go automatically dereferences
return (*item).Value // Explicit dereference
}
nil pointers are useful for:
nil pointer doesn't allocate memory)For this challenge, you need to implement the getWeaponDamage function that accepts a pointer to a Weapon and returns the damage value as an int.
The Weapon struct and main function are already provided. Your task is to:
nilnil, return 0 (no damage)nil, return the weapon's Damage valueThe function signature is:
func getWeaponDamage(weapon *Weapon) int {
// Your code here
}