0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Go 言語仕様9(構造体)

Last updated at Posted at 2021-02-14

概要

Go 言語の仕様まとめ。

前回:
Go 言語仕様8(ポインタ)

内容

  • 構造体
    • 宣言・代入
    • ポインタ
    • メソッド
    • 多重構造体
    • スライスとの合せ技

構造体

  • 宣言方法

構造体では、複数の任意の型を一つにまとめることができる。

宣言・代入
// 複数の任意の型を一つにまとめることができる
type Structure struct {
	// 外部パッケージがら呼び出せるように、先頭一文字は大文字にしておく
	Amount   int
	Language string
	Decimal  float64
	Bl       bool
}

func main() {
	// 変数の宣言方法と同じ
	var st Structure
	st2 := Structure{}
	// 各型の初期値が出力されることを確認
	fmt.Println(st) // {0  0 false}
	fmt.Println(st2) // {0  0 false}

	// 値を代入(.で各フィールドにアクセスできる)
	st.Amount = 1000
	st.Language = "Golang"
	fmt.Println(st.Amount, st.Language) // 1000 Golang

	// 初期値を指定して宣言
	st3 := Structure{
		Amount:   2000,
		Language: "Java",
		Decimal:  1.234,
		Bl:       true,
	}
	fmt.Println(st3) // {2000 Java 1.234 true}

	// 構造体のフィールドの順番で値のみを入れることも可能
	st4 := Structure{3000, "Python", 3.14, false}
	fmt.Println(st4)

	// 全フィールド分代入する必要がある
	st5 := Structure{3000, "Python", 3.14} // too few values in struct literal
}

  

  • ポインタ

構造体は値型のため、関数へ引数で渡したときなどは、元の構造体の値に影響がない。

値渡し
type Structure struct {
	Amount   int
	Language string
}

func Modify(st Structure) {
	st.Amount = 9999
	st.Language = "Golang"
}

func main() {
	var st Structure
	Modify(st)
	fmt.Println(st) // {0 }
}

そのため、ポインタ変数を作り、関数へ参照渡しする。

参照渡し
type Structure struct {
	Amount   int
	Language string
}

func Modify(st Structure) {
	st.Amount = 9999
	st.Language = "Golang"
}

func Modify2(st *Structure) {
	st.Amount = 9999
	st.Language = "Golang"
}

func main() {
	var st Structure
	Modify(st)
	fmt.Println(st)

	// 構造体のポインタを明示的に作る方法が推奨パターン
	st2 := &Structure{}
	Modify2(st2)
	fmt.Println(*st2) // {9999 Golang}

	// 非推奨パターンA
	st3 := Structure{}
	Modify2(&st3)

	// 非推奨パターンB
	st4 := new(Structure)
	Modify2(st4)
}

  

  • メソッド

 メソッド:
  構造体に紐付く処理群。紐付けた構造体でのみ使用可能。

 関数:
  構造体に紐付かない処理群。

 レシーバ:
  メソッドと紐付いた構造体。

関数を使った構造体の値更新
type Structure struct {
	Amount   int
	Language string
}

func Modify(st *Structure) {
	st.Amount = 2000
}

func main() {
	// 関数を使った構造体の値更新
	st := &Structure{100, "Golang"}
	Modify(st)
	fmt.Println(st) // &{2000 Golang}
}
メソッドを使った構造体の値更新
type Structure struct {
	Amount   int
	Language string
}

// メソッドのレシーバーはポインタ型にするのが一般的
func (st *Structure) Modify() {
	// レシーバーの値を書き換える
	st.Amount = 3000
}

func main() {
	st := &Structure{100, "Golang"}

	// レシーバー.メソッドで呼び出し
	st.Modify()
	fmt.Println(st) // &{3000 Golang}
}

  

  • 多重構造体

親子関係のような感じで、構造体を構造体のフィールドとして定義できる。

多重構造体
type SubStructure1 struct {
	Amount   int
	Language string
}

type SubStructure2 struct {
	Decimal float64
	Bl      bool
}

// 構造体をフィールドで持てる
type Structure struct {
	SubStructure1 SubStructure1
	// フィールド名が同じであれば、型宣言は省略可能
	SubStructure2
}

// メソッド
func (subst *SubStructure1) Modify() {
	subst.Amount = 9000
	subst.Language = "Java"
}

func main() {
	// 子の構造体にアクセスできる
	st2 := Structure{}
	fmt.Println(st2) // {{0 } {0 false}}

	// 値を入れる
	st2.SubStructure1.Amount = 100
	st2.SubStructure1.Language = "Golang"
	// 型宣言を省略した場合は、子の構造体に直接アクセス可能
	st2.Decimal = 1.234
	st2.Bl = true
	fmt.Println(st2) // {{100 Golang} {1.234 true}}

	// 値を入れつつ宣言
	st3 := Structure{
		SubStructure1: SubStructure1{
			Amount:   8000,
			Language: "Golang",
		},
	}
	fmt.Println(st3) // {{8000 Golang} {0 false}}

	// 親の構造体からこの構造体のメソッドを呼び出せる
	st2.SubStructure1.Modify()
	fmt.Println(st2)
}

  

  • スライスとの合せ技

構造体をスライスで扱える。

type Structure struct {
	Amount   int
	Language string
}

// 子の構造体をスライスでフィールドに持つ構造体
type SliceStruct struct {
	Structure []*Structure
}

func main() {
	// スライスで構造体を定義できる
	sl := make([]Structure, 3)
	fmt.Println(sl) // [{0 } {0 } {0 }]

	// 各スライスに値を代入
	sl[0].Amount = 100
	sl[1].Language = "Golang"
	sl[2].Amount = 200
	fmt.Println(sl) // [{100 } {0 Golang} {200 }]

	// スライスの構造体を定義して、
	v := Structure{100, "Galang"}
	v2 := Structure{100, "Java"}
	v3 := Structure{100, "Python"}
	// appendする
	slst := SliceStruct{}
	slst.Structure = append(slst.Structure, &v, &v2, &v3)
	// forで値を取り出す
	for _, v := range slst.Structure {
		fmt.Println(v)
	}
}

次回

Go 言語仕様10(テスト)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?