Goのアドレッサブルとノンアドレッサブルを1つの記事で理解する
1.アドレサブルとはどういう意味ですか?
演算子 & を使って直接アドレス指定できるオブジェクトは、アドレス指定可能です (
Addressable
). 例えば、次のような例です。
func main() {
name := "iswbm"
fmt.Println(&name)
// output: 0xc000010200
}
プログラムはエラーなく実行され、次のように表示されます。
name
変数がアドレス指定可能であることを示します。
でも、"はダメなんです。
iswbm
"この文字列はアドレス指定可能です。
"
iswbm
"は文字列であり、文字列は後述するように不変でアドレス指定ができない。
ひとつひとつ見ていく前に、まず結論から言うと
- ポインターは、&Profile{}に対応することができます。
- 変数がアドレス指定可能: name := Profile{}.
- リテラルな数量は全くアドレス指定できない。プロファイル{}
2. アドレサブルとは?
変数: &x
func main() {
name := "iswbm"
fmt.Println(&name)
// output: 0xc000010200
}
ポインタ: &*x
type Profile struct {
Name string
name string }
func main() {
fmt.Println(unsafe.Pointer(&Profile{Name: "iswbm"}))
// output: 0xc000108040
}
配列要素のインデックス:&a[0]。
func main() {
s := [...] int{1,2,3}
fmt.Println(&s[0])
// output: xc0000b4010
}
スライス
func main() {
fmt.Println([]int{1, 2, 3}[1:])
}
スライス要素インデックス:&s[1]。
func main() {
s := make([]int , 2, 2)
fmt.Println(&s[0])
// output: xc0000b4010
}
結合リテラル: &struct{X type}{value}。
すべての組合せリテラルは、次のようにアドレス指定不可です。
type Profile struct {
Name string
name string }
func new() Profile {
return Profile{Name: "iswbm"}
}
func main() {
fmt.Println(&new())
// cannot take the address of new()
}
上の書き出しとこの書き出しの違いに注意してください。この書き出しは、&がアドレスを取る操作ではなく、構造体をインスタンス化するポインタを表すという、異なる意味を持ちます。
type Profile struct {
Name string
name string }
func main() {
fmt.Println(&Profile{Name: "iswbm"}) // ok
}
結合されたリテラルはアドレス指定できませんが、結合されたリテラルのフィールド属性をアドレス指定(直接アクセス)することは可能です。
type Profile struct {
Name string
name string }
func new() Profile {
return Profile{Name: "iswbm"}
}
func main() {
fmt.Println(new().Name)
}
3. アドレス指定できないものは何ですか?
定数
import "fmt"
const VERSION = "1.0"
func main() {
fmt.Println(&VERSION)
}
文字列
func getStr() string {
return "iswbm"
}
func main() {
fmt.Println(&getStr())
// cannot take the address of getStr()
}
機能またはメソッド
func getStr() string {
return "iswbm"
}
func main() {
fmt.Println(&getStr)
// cannot take the address of getStr
}
基本的なタイプ・リテラル
リテラル量はに分けられる。 基本型リテラルと複合型リテラル。
値のテキスト表現である基本型リテラルは、想定外であり、対処できない。
func getInt() int {
return 1024
}
func main() {
fmt.Println(&getInt())
// cannot take the address of getInt()
}
マップ内の要素
辞書は特殊であり、2つの視点から逆算して導き出すことができる。辞書の要素がアドレス指定可能な場合、どうなるのだろうか。
辞書の要素が存在しない場合、ゼロ値を返します。ゼロ値は不変のオブジェクトなので、アドレス指定可能であれば大きな問題になります。
また、辞書の要素が存在する場合、仮にGo
map
の実装では、要素のアドレスは可変であるため、アドレス指定した結果も意味がないことになります。
この2点から、Mapの要素はアドレス指定できないのが常識です。
func main() {
p := map[string]string {
"name": "iswbm",
}
fmt.Println(&p["name"])
// cannot take the address of p["name"]
}
これを理解すれば、次のコードがなぜエラーを報告しているのか理解できるはずです。
package main
import "fmt"
type Person struct {
Name string
Email string
}
func main() {
m := map[int]Person{
1:Person{"Andy", "[email protected]"},
2:Person{"Tiny", "[email protected]"},
3:Person{"Jack", "[email protected]"}, 3:Person{"Jack", "[email protected]"},
}
//compile error: cannot assign to struct field m[1].Name in map
m[1].Name = "Scrapup"
配列リテラル
配列リテラルはアドレス指定できないので、配列リテラルをスライスするときは、実際には内部要素のアドレスを探していることになります。
func main() {
fmt.Println([3]int{1, 2, 3}[1:])
// invalid operation [3]int literal[1:] (slice of unaddressable value)
}
以上で、Goのアドレス指定可能・不可能についての記事を終了します。Goのアドレス指定可能、アドレス指定不可能については、Script Houseの過去の記事を検索するか、引き続き以下の関連記事を参照してください。
関連
最新
-
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 実装 サイバーパンク風ボタン