Go
Pointeurs
Recherche…
Syntaxe
- pointeur: = & variable // obtient le pointeur de la variable
- variable: = * pointeur // obtient la variable du pointeur
- * pointeur = valeur // définir la valeur de la variable via le pointeur
- pointeur: = new (Struct) // récupère le pointeur de la nouvelle structure
Pointeurs de base
Go prend en charge les pointeurs , vous permettant de transmettre des références aux valeurs et aux enregistrements de votre programme.
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
}
Une fois ces fonctions définies, vous pouvez effectuer les opérations suivantes:
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
}
Pointeur v. Méthodes de valeur
Méthodes de pointeur
Les méthodes de pointage peuvent être appelées même si la variable n'est pas elle-même un pointeur.
Selon le Go Spec ,
. . . une référence à une méthode sans interface avec un récepteur de pointeur utilisant une valeur adressable prendra automatiquement l'adresse de cette valeur:
t.Mp
est équivalent à(&t).Mp
.
Vous pouvez voir cela dans cet exemple:
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éthodes de valeur
Comme pour les méthodes de pointage, les méthodes de valeur peuvent être appelées même si la variable n'est pas elle-même une valeur.
Selon le Go Spec ,
. . . une référence à une méthode sans interface avec un récepteur de valeur utilisant un pointeur déréférencera automatiquement ce pointeur:
pt.Mv
est équivalent à(*pt).Mv
.
Vous pouvez voir cela dans cet exemple:
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)
}
Pour en savoir plus sur les méthodes de pointeur et de valeur, consultez la section Spécification de la méthode sur les valeurs de la méthode , ou consultez la section Mise en oeuvre effective concernant Pointers v. Values .
Note 1: La parenthèse ( ()
) autour de *p
et &f
avant que les sélecteurs comme .Bar
soient .Bar
à des fins de regroupement et doivent être conservés.
Note 2: Bien que les pointeurs puissent être convertis en valeurs (et vice-versa) lorsqu'ils sont les récepteurs d'une méthode, ils ne sont pas convertis automatiquement entre eux lorsqu'ils sont des arguments à l'intérieur d'une fonction.
Dereferencing Pointers
Les pointeurs peuvent être déréférencés en ajoutant un astérisque * avant un pointeur.
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
}
Les tranches sont des pointeurs vers des segments de tableau
Les tranches sont des pointeurs vers les tableaux, avec la longueur du segment et sa capacité. Ils se comportent comme des pointeurs et en attribuant leur valeur à une autre tranche, ils attribueront l'adresse mémoire. Pour copier une valeur de tranche dans une autre, utilisez la fonction de copie intégrée: func copy(dst, src []Type) int
(renvoie la quantité d'éléments copiés).
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
}
Pointeurs 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)
}