Je suppose que si j'essaie de passer un pointeur sur une fonction, cette déclaration de fonction devrait également recevoir un pointeur? Pas sûr, j'ai essayé ceci:

package main

import (
    "fmt"
)
type I interface {
    Get() int
    Set(int)
}

type S struct {
    Age int
}
func (s S) Get() int {
    return s.Age
}
func (s *S) Set(age int) {
    s.Age = age
}
func f(i I) {
    i.Set(10)
    fmt.Println(i.Get())
}
func main() {
    s := S{}
    f(&s) //4
    fmt.Println(s.Get())
}

Il imprime

10
10

On voit que la fonction de f est

func f(i I)

Je ne suis pas sûr que ce soit une déclaration "passe par valeur", si par valeur, alors "i" ne devrait pas être changé en dehors de la fonction "f" à droite, qui est une copie à l'intérieur de "f".

Alors, quel point me suis-je trompé?

-3
Troskyvs 4 nov. 2019 à 08:06

1 réponse

f(&s) transmet l'adresse du pointeur de s par valeur - comme tout autre appel de fonction go. Le fait que la fonction accepte un paramètre d'interface ne change rien à ce fait.

Maintenant concernant le fonctionnement de l'interface: une valeur d'interface contient 2 éléments: la valeur et le type sous-jacent. La valeur dans ce cas est le pointeur vers la structure. Le type vérifie que s satisfait l'interface - car il implémente les signatures de fonction Get / Set.

Puisqu'un récepteur de pointeur d'une méthode peut modifier les champs de données du récepteur - le &s peut être modifié par la méthode Set. Et par extension, appeler f(&s) - qui invoque Set - modifie donc également l'état de la structure s.

P.S. ce comportement est crucial pour la plupart des bibliothèques standard go. De nombreux packages, par exemple http s'appuient sur les interfaces io.Reader et io.Writer. Les fonctions et méthodes qui acceptent des valeurs qui implémentent ces interfaces reposent sur le changement d'état des types concrets sous-jacents, la lecture des ports réseau, le vidage des caches, etc. pour fonctionner - tout en n'alourdissant pas l'appelant de ces effets secondaires internes.

2
colm.anseo 4 nov. 2019 à 05:32