DMarlon Studio

Lección 16 · 16 de 20

Punteros · Go

Entienda los punteros en Go: & para obtener una dirección, * para llegar al valor, funciones que cambian el original y el valor nil.

Go · Punteros en DMarlon Studio: el código del ejemplo y su salida en la terminal

Un puntero guarda la dirección de una variable, el lugar donde está en la memoria. &score da esa dirección y ptr := &score la guarda; su tipo es *int, «puntero a int». Con *ptr se llega al valor: 120, el mismo que tiene score.

Al escribir a través del puntero se cambia la variable original: *ptr = 150 deja score en 150, aunque esa línea ni siquiera la nombre.

En Go los argumentos se pasan por copia. bonusCopy recibe un int y le suma 50, pero solo a su copia, que se pierde al terminar: score sigue en 150. bonus, en cambio, recibe un *int, la dirección, y *score += 50 cambia el original, que pasa a 200.

Con punteros a structs no hace falta el asterisco para los campos: dentro de levelUp, p.Score equivale a (*p).Score. &Player{...} crea el jugador y da directamente su dirección. El valor cero de un puntero es nil, que significa que no apunta a nada; usar un puntero nil detendría el programa, así que conviene comprobarlo antes.

Código · main.go

package mainimport "fmt"type Player struct {	Name  string	Score int}// Gets a copy of the number: the change is lost.func bonusCopy(score int) { score += 50 }// Gets the address: *score is the original variable.func bonus(score *int) { *score += 50 }// With a pointer to a struct, p.Score is enough (no * needed).func levelUp(p *Player) { p.Score += 100 }func main() {	score := 120	ptr := &score // & gives the address of the variable	fmt.Println("score:", score, "| *ptr:", *ptr)	*ptr = 150 // * reaches the value behind the address	fmt.Println("After *ptr = 150:", score)	bonusCopy(score)	fmt.Println("After bonusCopy:", score)	bonus(&score)	fmt.Println("After bonus:", score)	ana := &Player{Name: "Ana", Score: 10}	levelUp(ana)	fmt.Println(ana.Name, "now has", ana.Score, "points")	var nobody *Player // a pointer starts as nil	fmt.Println("nobody == nil:", nobody == nil)}

Salida · go run main.go

score: 120 | *ptr: 120
After *ptr = 150: 150
After bonusCopy: 150
After bonus: 200
Ana now has 110 points
nobody == nil: true

Para recordar

  • &x da la dirección de x; su tipo es *T.
  • *p lee o cambia el valor al que apunta p.
  • Pase un puntero para que una función cambie el original.
  • Con un puntero a struct, p.Campo basta.
  • Un puntero sin valor es nil.

Ejercicio

Escriba func swap(a, b *int), que intercambie dos variables, y pruébela; después, func resetScore(p *Player), que ponga la puntuación a cero.