[解決済み] Go オブジェクトのポインタ値を表示するにはどうすればよいですか?ポインタの値は何を意味するのですか?
質問
私はGoで遊んでいるだけで、構造体が値で渡される場合と参照で渡される場合について、まだ良いメンタルモデルを持っていません。
これは非常に馬鹿げた質問かもしれませんが、少し実験して、同じオブジェクトでまだ作業しているか、そのコピーを作成したか(値で渡した)どうかを確認したいだけです。
オブジェクトのポインタ(またはポインタの値がgcによって変更された場合、内部ID)を表示する方法はありますか?
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)
}
は、私のWindows(8gコンパイル版)上で動作します。
0x4930d4
from gotest:
0x4974d8
42
0x4930d4
42
goルーチン内からのポインタの値が異なるのはなぜですか?元のオブジェクトの数量は変更されたので、同じオブジェクトで動作しています。永続的なオブジェクト ID を確認する方法はありますか?
どのように解決するのですか?
Go関数の引数は値で渡されます。
まず、例の無関係な部分を捨てて、単に値で引数を渡していることが簡単にわかるようにしましょう。たとえば
package main
import "fmt"
func byval(q *int) {
fmt.Printf("3. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
*q = 4143
fmt.Printf("4. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
q = nil
}
func main() {
i := int(42)
fmt.Printf("1. main -- i %T: &i=%p i=%v\n", i, &i, i)
p := &i
fmt.Printf("2. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
byval(p)
fmt.Printf("5. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
fmt.Printf("6. main -- i %T: &i=%p i=%v\n", i, &i, i)
}
出力します。
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
機能では
main
,
i
は
int
変数で、メモリ位置 (
&i
)
0xf800000040
を初期値として (
i
)
42
.
関数内
main
,
p
へのポインタです。
int
変数へのポインタです。
&p
)
0xf8000000f0
という値を持つ (
p
=
&i
)
0xf800000040
を指している
int
の値 (
*p
=
i
)
42
.
関数内
main
,
byval(p)
は関数呼び出しで、値 (
p
=
&i
)
0xf800000040
メモリ位置の引数の(
&p
)
0xf8000000f0
を関数
byval
パラメータ
q
をメモリ位置(
&q
)
0xf8000000d8
. つまり、メモリが確保されるのは
byval
パラメータ
q
の値と
main
byval
引数
p
が代入されます。
p
と
q
は最初は同じですが、変数
p
と
q
は区別されます。
関数では
byval
で、ポインタを用いて
q
(
*int
) のコピーであり、これはポインタ
p
(
*int
), 整数
*q
(
i
) には新しい int 値が設定されます。
4143
. 最後にリターンする前に、ポインタ
q
に設定されます。
nil
(ゼロ値) であり、これは
p
であるため
q
はコピーだからです。
関数では
main
,
p
へのポインタです。
int
変数へのポインタです。
&p
)
0xf8000000f0
という値を持つ (
p
=
&i
)
0xf800000040
を指し、新しい
int
の値 (
*p
=
i
)
4143
.
関数内
main
,
i
は
int
変数で、メモリ位置 (
&i
)
0xf800000040
を最終値として (
i
)
4143
.
あなたの例では、関数
main
変数
s
関数の引数として使われる
gotest
の呼び出しは、関数
gotest
パラメータ
s
. これらは同じ名前ですが、スコープとメモリ位置が異なる別の変数です。関数パラメータ
s
は関数呼び出しの引数
s
. このため、私の例では、引数とパラメータの変数名を
p
と
q
をそれぞれ使って違いを強調しています。
あなたの例では、(
&s
)
0x4930d4
は変数のメモリ位置のアドレスです。
s
関数内の
main
は、関数呼び出しの引数として使用されます。
gotest(s, done)
と
0x4974d8
は関数のメモリ位置のアドレスです。
gotest
パラメータ
s
. もし、パラメータ
s = nil
を関数の最後に設定すると
gotest
に対して何の効果もありません。
s
で
main
;
s
で
main
と
s
で
gotest
は異なるメモリ位置である。タイプで言えば
&s
は
**Something
,
s
は
*Something
であり、かつ
*s
は
Something
.
&s
は (メモリ位置のアドレス) へのポインタです。
s
型の無名変数へのポインタである。
Something
. 値の観点からは
main.&s != gotest.&s
,
main.s == gotest.s
,
main.*s == gotest.*s
そして
main.s.number == gotest.s.number
.
mkb の賢明なアドバイスに従って、あなたは
println(&s)
. を使いましょう。
fmt
というパッケージを使用します。
fmt.Printf("%v %p %v\n", &s, s, *s)
ポインターは、同じメモリ位置を指しているときは同じ値を持ち、異なるメモリ位置を指しているときは異なる値を持ちます。
関連
-
[解決済み] Goでint値をstringに変換する方法は?
-
[解決済み] 構造体変数をコンソールに表示するには?
-
[解決済み] Goでオブジェクトの型を見つけるには?
-
[解決済み】Goのタグはどのような用途に使われますか?
-
[解決済み】import文の前にあるアンダースコアは何を意味するのですか?
-
[解決済み] os.Exit()とpanic()はいつ使うのか?
-
[解決済み] Goのargv[0]に相当するものは何ですか?
-
[解決済み] 構造体の値をマップの値として設定すると、"cannot assign" エラーが発生するのはなぜですか?重複
-
[解決済み] テキストファイルの読み方を教えてください。重複
-
[解決済み] IntelliJでファイル保存時にgofmtを実行する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] time.Sleepを使わずにすべてのゴルーチンが終了するのを待つには?
-
[解決済み] Goで関数の名前を取得するには?
-
[解決済み] os.Exit()とpanic()はいつ使うのか?
-
[解決済み] golangでは、マップから値のスライスを取得する良い方法はありますか?
-
[解決済み] go モジュール内のローカルパッケージへのアクセス (go 1.11)
-
[解決済み] スライスを変数入力として渡すには?
-
[解決済み] 文字列を小文字に変換する方法を教えてください。
-
[解決済み] 空のスライスをチェックするにはどうしたらいいですか?
-
[解決済み] golangでISO 8601の時刻を変換するには?
-
[解決済み] 文字列がint型かどうかチェックする