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
}

Prueba este codigo

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)
}

Juegalo

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)
}

Juegalo


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)
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow