Comment puis-je imprimer la valeur du pointeur d’un object Go? Que signifie la valeur du pointeur?

Je ne fais que jouer avec Go et je n’ai pas encore un bon modèle mental pour savoir quand les structures sont passées par valeur ou par référence.

C’est peut-être une question très stupide mais je veux juste expérimenter un peu et voir si je travaille toujours sur le même object ou si j’en ai fait une copie (passée par valeur).

Est-il possible d’imprimer le pointeur (ou l’ID interne si la valeur du pointeur est modifiée par gc) d’un object?

package main import ( "runtime" ) type Something struct { number int queue chan int } func gotest( s *Something, done chan bool ) { println( "from gotest:") println( &s ) for num := range s.queue { println( num ) s.number = num } done <- true } func main() { runtime.GOMAXPROCS(4) s := new(Something) println(&s) s.queue = make(chan int) done := make(chan bool) go gotest(s, done) s.queue <- 42 close(s.queue) <- done println(&s) println(s.number) } 

donne sur mes fenêtres (version compilée 8g):

 0x4930d4 from gotest: 0x4974d8 42 0x4930d4 42 

Pourquoi la valeur du pointeur dans la routine go affiche-t-elle une valeur différente? La quantité sur l’object d’origine a été modifiée pour fonctionner avec le même object. Est-il possible de voir un identifiant d’object persistant?

Les arguments de la fonction Go sont passés par valeur.

Tout d’abord, écartons les parties non pertinentes de votre exemple, afin que nous puissions facilement voir que vous transmettez simplement un argument par valeur. Par exemple,

 package main import "fmt" func byval(q *int) { fmt.Printf("3. byval -- q %T: &q=%pq=&i=%p *q=i=%v\n", q, &q, q, *q) *q = 4143 fmt.Printf("4. byval -- q %T: &q=%pq=&i=%p *q=i=%v\n", q, &q, q, *q) q = nil } func main() { i := int(42) fmt.Printf("1. main -- i %T: &i=%pi=%v\n", i, &i, i) p := &i fmt.Printf("2. main -- p %T: &p=%pp=&i=%p *p=i=%v\n", p, &p, p, *p) byval(p) fmt.Printf("5. main -- p %T: &p=%pp=&i=%p *p=i=%v\n", p, &p, p, *p) fmt.Printf("6. main -- i %T: &i=%pi=%v\n", i, &i, i) } 

Sortie:

 1. main -- i int: &i=0xf840000040 i=42 2. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=42 3. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=42 4. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=4143 5. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=4143 6. main -- i int: &i=0xf840000040 i=4143 

Dans la fonction main , i est une variable int à l’emplacement de la mémoire ( &i ) 0xf800000040 avec une valeur initiale ( i ) 42 .

Dans la fonction main , p est un pointeur sur une variable int à l’emplacement de la mémoire ( &p ) 0xf8000000f0 avec une valeur ( p = &i ) 0xf800000040 qui pointe sur une valeur int ( *p = i ) 42 .

Dans la fonction main , byval(p) est un appel de fonction qui affecte la valeur ( p = &i ) 0xf800000040 de l’argument à l’emplacement de la mémoire ( &p ) 0xf8000000f0 au paramètre byval fonction q à l’emplacement de la mémoire ( &q ) 0xf8000000d8 . En d’autres termes, la mémoire est allouée pour le paramètre byval q et la valeur de l’argument byval main p est affectée; les valeurs de p et q sont initialement les mêmes, mais les variables p et q sont distinctes.

Dans la fonction byval , en utilisant le pointeur q ( *int ), qui est une copie du pointeur p ( *int ), entier *q ( i ) est défini sur une nouvelle valeur int 4143 . À la fin avant de revenir. le pointeur q est mis à nil (valeur zéro), ce qui n’a aucun effet sur p car q est une copie.

Dans la fonction main , p est un pointeur sur une variable int à l’emplacement de la mémoire ( &p ) 0xf8000000f0 avec une valeur ( p = &i ) 0xf800000040 qui pointe vers une nouvelle valeur int ( *p = i ) 4143 .

Dans la fonction main , i est une variable int à l’emplacement de la mémoire ( &i ) 0xf800000040 avec une valeur finale ( i ) 4143 .

Dans votre exemple, la variable main la fonction utilisée comme argument de la fonction gotest est différente de la fonction gotest paramètre s . Ils ont le même nom, mais sont des variables différentes avec des scopes et des emplacements de mémoire différents. Le paramètre de fonction s masque les arguments d’appel de fonction s . C’est pourquoi dans mon exemple, j’ai nommé l’argument et les variables de paramètre p et q respectivement pour souligner la différence.

Dans votre exemple, ( &s ) 0x4930d4 est l’adresse de l’emplacement mémoire de la variable s dans la fonction main qui est utilisée comme argument pour l’appel de fonction gotest(s, done) , et 0x4974d8 est l’adresse de l’emplacement mémoire du fonction paramètre gotest s . Si vous définissez le paramètre s = nil à la fin de la fonction gotest , cela n’a aucun effet sur les variables s dans main ; s en main et s en gotest sont des emplacements de mémoire distincts. En termes de types, &s est **Something , s est *Something , et *s est Something . &s est un pointeur sur (adresse de l’emplacement de la mémoire) s , qui est un pointeur sur (adresse de l’emplacement de la mémoire) une variable anonyme de type Something . En termes de valeurs, main.&s != gotest.&s , main.s == gotest.s , main.*s == gotest.*s , et main.s.number == gotest.s.number .

Vous devriez prendre les conseils de mkb et cesser d’utiliser println(&s) . Utilisez le package fmt , par exemple,

 fmt.Printf("%v %p %v\n", &s, s, *s) 

Les pointeurs ont la même valeur lorsqu’ils pointent vers le même emplacement mémoire. les pointeurs ont des valeurs différentes lorsqu’ils indiquent des emplacements de mémoire différents.

Dans Go, les arguments sont passés par valeur.

 package main import "fmt" type SomeStruct struct { e int } // struct passed by value func v(v SomeStruct) { fmt.Printf("v: %p %v\n", &v, v) ve = 2 fmt.Printf("v: %p %v\n", &v, v) } // pointer to struct passed by value func p(p *SomeStruct) { fmt.Printf("p: %p %v\n", p, *p) pe = 2 fmt.Printf("p: %p %v\n", p, *p) } func main() { var s SomeStruct se = 1 fmt.Printf("s: %p %v\n", &s, s) v(s) fmt.Printf("s: %p %v\n", &s, s) p(&s) fmt.Printf("s: %p %v\n", &s, s) } 

Sortie:

 s: 0xf800000040 {1} v: 0xf8000000e0 {1} v: 0xf8000000e0 {2} s: 0xf800000040 {1} p: 0xf800000040 {1} p: 0xf800000040 {2} s: 0xf800000040 {2} 
 type sometype struct { } a := sometype {} b := int(2) println("Ptr to a", &a) println("Ptr to b", &b) 
 package main import "fmt" func zeroval(ival int) { ival = 0 } func zeroptr(iptr *int) { *iptr = 0 } func main() { i := 1 fmt.Println("initial:", i) zeroval(i) fmt.Println("zeroval:", i) //The &i syntax gives the memory address of i, ie a pointer to i. zeroptr(&i) fmt.Println("zeroptr:", i) //Pointers can be printed too. fmt.Println("pointer:", &i) } 

SORTIE:

 $ go run pointers.go initial: 1 zeroval: 1 zeroptr: 0 pointer: 0x42131100 

Comment imprimer la valeur du pointeur d’un object Go?

 package main import ( "fmt" ) func main() { a := 42 fmt.Println(&a) } 

résulte en:

 0x1040a124 

Que signifie la valeur du pointeur?

Selon Wikipedia :

Un pointeur référence un emplacement en mémoire