34 ポインタ
&(アンパサンド)はアドレスを持ってくる時に使用する。
はポインタ型の変数だと明示する際に使用。
アドレスを格納したポインタ型の実体を参照する場合、ポインタ型の変数にを付ける。
package main
import "fmt"
func main() {
var x int = 10
var y *int = &x
log.Printf("x: %v", x) // x: 10
log.Printf("x: %v", &x) // x: 0x1400000ee10
log.Printf("y: %v", y) // x: 0x1400000ee10
log.Printf("y: %v", *y) // x: 10
}
実行結果.go
10
0xc0000160c8
0xc0000160c8
10
package main
import "fmt"
func increment(num *int) {
// 824633794672
fmt.Printf("num: %d\n", num)
*num = *num + 1
}
func main() {
value := 10
fmt.Println("Before:", value)
// ポインタを渡す
increment(&value)
// 824633794672
fmt.Printf("&value: %d\n", &value)
fmt.Println("After:", value)
}
実行結果.go
Before: 10
num: 824633794672
&value: 824633794672
After: 11
36 struct
package main
import "fmt"
type Vertex struct {
X, Y int
S string
}
func main() {
v := Vertex{X: 1, Y: 2, S: "ver"}
fmt.Println(v)
v4 := Vertex{}
fmt.Printf("%T %v\n", v, v4)
var v5 Vertex
fmt.Printf("%T %v\n", v5, v5)
// ポインタ
v6 := new(Vertex)
fmt.Printf("%T %v\n", v6, v6)
// 推奨
v7 := &Vertex{}
fmt.Printf("%T %v\n", v7, v7)
// スライス
// 推奨
s1 := make([]int, 0)
fmt.Println(s1)
s2 := []int{}
fmt.Println(s2)
}
v4,v5の方法で制限するやり方と、v6,v7のやり方では違うものが宣言されているので注意。
ポインタとしての宣言方法はv7のほうが推奨されている(アンパサンドがついていてポインタを定義しているとわかりやすい)
同様にスライスも定義の仕方が複数あるが、s1のほうが推奨されている
※この講座自体少し前の情報のため変わっているかも
package main
import "fmt"
type Vertex struct {
X, Y int
S string
}
func changeVertex(v Vertex) {
v.X = 1000
}
func changeVertex2(v *Vertex) {
v.X = 1000
}
func main() {
v := Vertex{X: 1, Y: 2, S: "ver"}
changeVertex(v)
fmt.Println(v)
v2 := &Vertex{X: 1, Y: 2, S: "ver"}
changeVertex2(v2)
fmt.Println(v2)
}
実行結果.go
{1 2 ver}
{1000 2 ver}
構造体の値を書き換えたいとき
vはchangeVertex()の関数内でのみ変数が書き換わるが、mainには影響がない。
書き換えたい場合はv2のように、構造体を宣言する際にアンパサンド&をつける。
changeVertex2()を実行するときに渡しているのは、構造体が格納されているメモリのアドレスになる。
関数の引数にアスタリスクをつければ、渡ってきたメモリのアドレスから中身を参照することができるため、値を書き換える事ができる。