Buscar..
Sintaxis
- puntero: = & variable // obtener puntero de variable
- variable: = * puntero // obtener variable desde puntero
- * puntero = valor // establecer el valor de la variable a través del puntero
- puntero: = nuevo (Struct) // obtener puntero de nueva estructura
Punteros básicos
Go admite punteros , lo que le permite pasar referencias a valores y registros dentro de su programa.
package main
import "fmt"
// We'll show how pointers work in contrast to values with
// 2 functions: `zeroval` and `zeroptr`. `zeroval` has an
// `int` parameter, so arguments will be passed to it by
// value. `zeroval` will get a copy of `ival` distinct
// from the one in the calling function.
func zeroval(ival int) {
ival = 0
}
// `zeroptr` in contrast has an `*int` parameter, meaning
// that it takes an `int` pointer. The `*iptr` code in the
// function body then _dereferences_ the pointer from its
// memory address to the current value at that address.
// Assigning a value to a dereferenced pointer changes the
// value at the referenced address.
func zeroptr(iptr *int) {
*iptr = 0
}
Una vez que estas funciones están definidas, puedes hacer lo siguiente:
func main() {
i := 1
fmt.Println("initial:", i) // initial: 1
zeroval(i)
fmt.Println("zeroval:", i) // zeroval: 1
// `i` is still equal to 1 because `zeroval` edited
// a "copy" of `i`, not the original.
// The `&i` syntax gives the memory address of `i`,
// i.e. a pointer to `i`. When calling `zeroptr`,
// it will edit the "original" `i`.
zeroptr(&i)
fmt.Println("zeroptr:", i) // zeroptr: 0
// Pointers can be printed too.
fmt.Println("pointer:", &i) // pointer: 0x10434114
}
Puntero v. Métodos de valor
Métodos de puntero
Los métodos de puntero se pueden llamar incluso si la variable no es un puntero.
Según la especificación de Go ,
. . . una referencia a un método sin interfaz con un receptor de puntero que usa un valor direccionable tomará automáticamente la dirección de ese valor:
t.Mp
es equivalente a(&t).Mp
.
Puedes ver esto en este ejemplo:
package main
import "fmt"
type Foo struct {
Bar int
}
func (f *Foo) Increment() {
f.Bar += 1
}
func main() {
var f Foo
// Calling `f.Increment` is automatically changed to `(&f).Increment` by the compiler.
f = Foo{}
fmt.Printf("f.Bar is %d\n", f.Bar)
f.Increment()
fmt.Printf("f.Bar is %d\n", f.Bar)
// As you can see, calling `(&f).Increment` directly does the same thing.
f = Foo{}
fmt.Printf("f.Bar is %d\n", f.Bar)
(&f).Increment()
fmt.Printf("f.Bar is %d\n", f.Bar)
}
Métodos de valor
De manera similar a los métodos de puntero, los métodos de valor pueden invocarse incluso si la variable en sí misma no es un valor.
Según la especificación de Go ,
. . . una referencia a un método sin interfaz con un receptor de valores que utiliza un puntero
pt.Mv
automáticamente la referencia de que el puntero:pt.Mv
es equivalente a(*pt).Mv
.
Puedes ver esto en este ejemplo:
package main
import "fmt"
type Foo struct {
Bar int
}
func (f Foo) Increment() {
f.Bar += 1
}
func main() {
var p *Foo
// Calling `p.Increment` is automatically changed to `(*p).Increment` by the compiler.
// (Note that `*p` is going to remain at 0 because a copy of `*p`, and not the original `*p` are being edited)
p = &Foo{}
fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
p.Increment()
fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
// As you can see, calling `(*p).Increment` directly does the same thing.
p = &Foo{}
fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
(*p).Increment()
fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
}
Para obtener más información sobre los métodos de puntero y valor, visite la sección Go Spec en Valores del método , o consulte la sección Effective Go acerca de los punteros v. Valores .
Nota 1: Los paréntesis ( ()
) alrededor de *p
y &f
antes de los selectores como .Bar
están allí para propósitos de agrupación, y deben mantenerse.
Nota 2: Aunque los punteros se pueden convertir a valores (y viceversa) cuando son los receptores de un método, no se convierten automáticamente a otros cuando son argumentos dentro de una función.
Desreferenciación de punteros
Los punteros se pueden eliminar de referencia agregando un asterisco * antes de un puntero.
package main
import (
"fmt"
)
type Person struct {
Name string
}
func main() {
c := new(Person) // returns pointer
c.Name = "Catherine"
fmt.Println(c.Name) // prints: Catherine
d := c
d.Name = "Daniel"
fmt.Println(c.Name) // prints: Daniel
// Adding an Asterix before a pointer dereferences the pointer
i := *d
i.Name = "Ines"
fmt.Println(c.Name) // prints: Daniel
fmt.Println(d.Name) // prints: Daniel
fmt.Println(i.Name) // prints: Ines
}
Las rebanadas son punteros a segmentos de matriz
Los segmentos son punteros a matrices, con la longitud del segmento y su capacidad. Se comportan como punteros, y asignando su valor a otra porción, asignarán la dirección de memoria. Para copiar un valor de sector a otro, use la función de copia incorporada: func copy(dst, src []Type) int
(devuelve la cantidad de elementos copiados).
package main
import (
"fmt"
)
func main() {
x := []byte{'a', 'b', 'c'}
fmt.Printf("%s", x) // prints: abc
y := x
y[0], y[1], y[2] = 'x', 'y', 'z'
fmt.Printf("%s", x) // prints: xyz
z := make([]byte, len(x))
// To copy the value to another slice, but
// but not the memory address use copy:
_ = copy(z, x) // returns count of items copied
fmt.Printf("%s", z) // prints: xyz
z[0], z[1], z[2] = 'a', 'b', 'c'
fmt.Printf("%s", x) // prints: xyz
fmt.Printf("%s", z) // prints: abc
}
Punteros simples
func swap(x, y *int) {
*x, *y = *y, *x
}
func main() {
x := int(1)
y := int(2)
// variable addresses
swap(&x, &y)
fmt.Println(x, y)
}