うおのめマリーの満遊記

都会の団地でプー太郎をしているエンジニアの日常。たまに軽く仕事とったりしながらまったりとスローライフを満喫中。料理が得意です。

Go ポインタ編

Go ポインタ編

ポインタ

package main
import "fmt"

func main(){
    var n int = 100
    fmt.Println(n) // 100
    
    // &(アンパサンド)はメモリのアドレスを表す
    fmt.Println(&n) // >>> 0xc00001a040 (変数nのメモリアドレス)
    
    // *intでポインタ変数の定義ができ、変数への格納はメモリアドレスを渡す
    var p *int = &n 
    
    fmt.Println(p) // >>> 0xc00001a040
    
    // *ポインタ変数 で実体値にアクセスできる(デリファレンスと読んだりもする)
    fmt.Println(*p) // 100
}

*デリファレンス(dereference)

何かを参照しているものの参照先を見に行くこと。

変数とポインタ変数の挙動の違い
func one(x int){
    x = 1
}

func main(){
    var n int = 100
    one(n)
    // func oneでは書き換えが行われずに100
    fmt.Println(n) // >>> 100
}
func two(x *int){
    *x = 1 // *xで実体(n)にアクセスし書き換え
}

func main(){
    var n int = 100
    two(&n)  // 変数nのメモリのアドレスを渡す
    fmt.Println(n) // >>> 1
}

new

値を入れずにメモリにアドレスだけを確保したい場合はnewを使う

package main

import "fmt"

func main(){
    // メモリにアドレスだけを確保したい場合はnewを使う
    var p *int = new(int)
    fmt.Println(p) // >>>0xc0000a0000
    
    // 中身の実体値は0が入っている
    fmt.Println(p) // >>> 0
    
    // newをしない場合はポインタ型変数の宣言をしてもメモリを確保がされていない
    var p2 *int
    fmt.Println(p2) // >>> nil
    
    // 中身を確認すると panicでerrorが返却される
    fmt.Println(*p2)
}

struct

package main
import "fmt"

// capital paburiku
// プライベートになる

type Vertex struct{
    X int
    Y int
}

func main() {
 v := Vertex{X:1, Y:2}
 fmt.Println(v)
 // vの中にもアクセスできる
 fmt.Println(v.X, v.Y)
 // 中身の書き換え
 v.X = 100
 fmt.Println(v.X, v.Y)

type Vertex2 struct{
    X int
    Y int
    S string
}
func main() {
 v := Vertex{X:1, Y:2}
 fmt.Println(v)
 // vの中にもアクセスできる
 fmt.Println(v.X, v.Y)
 // 中身の書き換え
 v.X = 100
 fmt.Println(v.X, v.Y)
 
 // 指定していなければデフォルトのint 0が挿入される(stringであれば空)
 v2 := Vertex{X: 1}
 fmt.Println(v2) // >>> {1 0}

 // structの中身を指定しない場合は順番通り入れればOK   
 v3 := Vertex2{1, 2, "test"}
 fmt.Println(v3) // >>> {1 2 test}

 // 全て指定しなければデフォルトで返却される
 v4 := Vertex2{}
 fmt.Println(v4) // >>> {0 0 }
 fmt.Printf("%T %v\n", v4, v4)
 
 // nilにはならない sliceやmapはnilになる
 var v5 Vertex2
 fmt.Printf("%T %v\n", v5, v5)
 
 v6 :=new(Vertex2)
 fmt.Printf("%T %v\n", v6, v6) // pointerが帰ってきている
 
 v7 := &Vertex2{} // こっちを使う人の方が多い気がする
 fmt.Printf("%T %v\n", v7, v7) // pointerが帰ってきている
 
 s := []int{}
 s := []int{}

}