概要
構造体(Struct)とポインタの使用イメージが沸かなかったので実装イメージを記述してみた。
ポインタとは
- ポインタとは、他の変数のメモリアドレスを指す変数
- ポインタを使うと、変数の値を更新する際、ポインタを使って直接更新可能
- ポインタを使うことで、関数間で変数の値を受け渡しする際など、コードをより効率的に記述可能
Goにおけるポインタ
Goでは、ポインタは*
を使って宣言します。
// int型のポインタを宣言
var p *int
ポインタを使って変数の値を変更するには、&
を使い、変数のアドレスを取得します。
// 変数xを初期化
x := 10
// pにxのアドレスを代入
p = &x
// pを使ってxの値を変更
*p = 20
// xの値を表示
fmt.Println(x) // => 20
構造体(Struct)とは
- 構造体とは、複数のデータをまとめて1つのデータとして扱うデータ型
- データ型の構造を定義し、それぞれのデータをメンバと呼ばれる要素として定義
- 構造体を使うと、複雑なデータ構造を簡単に表現可能
Goにおける構造体(Struct)とは
Goにおける構造体とは、複数のデータをまとめて1つのデータとして扱うためのデータ型です。Go言語では、構造体を次のように宣言します。
type <構造体名> struct {
メンバ1 型
メンバ2 型
...
}
各構造体のメンバにアクセスするために、次のようにドット演算子(.)を使います。
構造体変数.メンバ
(本題)ポインタを用いて構造体の値を更新する方法
package main
import "fmt"
type User struct {
Name string
Age int
}
// User型を引数として受け取る
func UpdateUser1(user User) {
user.Name = "AfterUser"
user.Age = 99999999999
}
// Userのポインタ型を引数として受け取る
func UpdateUser2(user *User) {
user.Name = "AfterUser"
user.Age = 99999999999
}
func main() {
// 構造体に初期値を入れて変数に入れる
user1 := User{Name: "user1", Age: 30}
// アドレス演算子を指定して宣言する
user2 := &User{}
// 中身は初期値が入っている
fmt.Println(user1)
// → {user1 30}
// Userのポインタ型が入っている
fmt.Println(user2)
// → &{ 0}
// 構造体の中身を変更してみる
UpdateUser1(user1)
UpdateUser2(user2)
// 中身は変わっていない
fmt.Println(user1)
// → {user1 30}
// 中身が更新されている
fmt.Println(user2)
// → &{AfterUser 99999999999}
}
なぜポインタで渡さないと値が更新されないのか
// User型を引数として受け取る
func UpdateUser1(user User) {
user.Name = "AfterUser"
user.Age = 99999999999
}
この関数はUserの構造体を実体として渡しているため、コピーが生成され値が反映されない。
// Userのポインタ型を引数として受け取る
func UpdateUser2(user *User) {
user.Name = "AfterUser"
user.Age = 99999999999
}
この関数はUserのアドレスをとして渡しているため、参照渡しができているため、値が反映されている。
あとがき
わかりにくかったり、間違ってたら教えてください!!