Goには複数の変数宣言(メモリ割り当てと値の初期化方法)がある
&T{...}、 &someLocalVar、 new、 make など
ポインタ型
基本こちらで理解
自分なりの整理
・ポインタ型とはメモリアドレスを格納することができる変数
→ ポインタ型(=大元アドレス保持型)
→ 指定された変数のアドレスを保持、その大元アドレスを参照し新たにデータ領域を作成する
【ポインタ型の宣言】 「new」 または 「&変数 によるアドレス指定」
基本こちらで理解
Is there a difference between new() and “regular” allocation?
自分なりの整理
・newのカッコに任意のタイプ型を指定する(または &変数名 でアドレスを指定する)
→ 大元アドレスが渡される
→ その大元アドレスを参照し新たにデータ領域が作成される
→ 受け取り側の変数はポインタ型(タイプ型名の前に*をつける)にする
→ 0で初期化される(不要な初期化時間や領域確保をなくす)
【例:宣言の仕方】
func main() {
var a *int = new(int) // OK
b := new(int) // OK
c := &int // NG (Not work this address set)
// Works, but it is less convenient to write than new(int)
var d int
x := &d
}
【例:ストラクトとポインタ】
type House struct {
Name string
Room int
}
func main() {
v := House{"YourHouse", 2} // Without pointer
fmt.Println(v)
a := new(House) // OK
b := &House{} // OK
c := &House{"MyHouse", 3} // Combines allocation and initialization
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
結果
{YourHouse 2}
&{ 0}
&{ 0}
&{MyHouse 3}
→結果に表示される & は大元アドレス保持しているよという意味(=ポインタ型)
【例:関数とポインタ】
func three(x *int) {
*x = 3 // アドレスの中身を変更
}
func main() {
var a int = 100
three(&a) // アドレスを渡す
fmt.Println(a) // 値が変更されている
}
結果
3
「make」による変数宣言
基本こちらで理解
Go: Make slices, maps and channels
Which is the nicer way to initialize a map in Golang?
自分なりの整理
・slice,map,channelのみで使用される
・メモリの領域を指定できる(予め領域確保することでリサイズなどが発生しにくいのかも)
・使う前にmakeで初期化した方が良いときがある(特にchannel?)
(mapは15個程データがあるならmakeにした方が良いとか)
・それぞれのタイプ型で初期化される(Structの中身を確認すると良い)
// 固定長配列を定義
a := [4]int{1, 2, 3, 4}
// サイズ等を持ったスライスを定義
b := make([]int, 4, 8)
// バッファー無しのチャネル
c := make(chan string)
// バッファー有りのチャネル
d := make(chan string, 10)