Szukaj…


Składnia

  • wskaźnik: = i zmienna // pobierz wskaźnik ze zmiennej
  • zmienna: = * wskaźnik // pobierz zmienną ze wskaźnika
  • * wskaźnik = wartość // ustaw wartość od zmiennej poprzez wskaźnik
  • pointer: = new (Struct) // pobierz wskaźnik nowej struktury

Podstawowe wskaźniki

Go obsługuje wskaźniki , pozwalając na przekazywanie referencji do wartości i rekordów w twoim programie.

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
}

Po zdefiniowaniu tych funkcji możesz wykonać następujące czynności:

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
}

Wypróbuj ten kod

Wskaźnik v. Metody wartości

Metody wskaźnika

Metody wskaźnikowe można wywoływać, nawet jeśli zmienna sama w sobie nie jest wskaźnikiem.

Według specyfikacji Go ,

. . . odniesienie do metody nieinterfejsowej z odbiornikiem wskaźnikowym wykorzystującej wartość adresowalną automatycznie przyjmuje adres tej wartości: t.Mp jest równoważne (&t).Mp .

Możesz to zobaczyć w tym przykładzie:

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

Graj

Metody wyceny

Podobnie jak w przypadku metod wskaźnikowych, metody wartości można wywoływać, nawet jeśli sama zmienna nie jest wartością.

Według specyfikacji Go ,

. . . odniesienie do metody nieinterfejsowej z odbiornikiem wartości za pomocą wskaźnika automatycznie pt.Mv ten wskaźnik: pt.Mv jest równoważne (*pt).Mv .

Możesz to zobaczyć w tym przykładzie:

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

Graj


Aby dowiedzieć się więcej o metodach wskaźnikowych i wartościowych, odwiedź sekcję Go Spec w Method Values lub zobacz Efektywną wersję Go o Pointers v. Values .


Uwaga 1: Nawiasy ( () ) wokół *p i &f przed selektorami, takimi jak .Bar służą do grupowania i muszą zostać zachowane.

Uwaga 2: Chociaż wskaźniki mogą być konwertowane na wartości (i odwrotnie), gdy są odbiornikami metody, nie są one automatycznie konwertowane na siebie, gdy są argumentami wewnątrz funkcji.

Wskaźniki dereferencyjne

Wskaźniki mogą być dereferencjonowane dodając gwiazdkę * przed wskaźnikiem.

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
}

Plasterki są wskaźnikami do segmentów macierzy

Plasterki są wskaźnikami do tablic, o długości segmentu i jego pojemności. Zachowują się jak wskaźniki, a przypisanie ich wartości do innego wycinka spowoduje przypisanie adresu pamięci. Aby skopiować wartość wycinka do innej, użyj wbudowanej funkcji kopiowania : func copy(dst, src []Type) int (zwraca liczbę skopiowanych elementów).

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
}

Proste wskaźniki

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow