Skip to Content

入門Goプログラミング Lesson21(構造体)から学んだこと

構造体

関係のある複数の値を1つのグループにまとめる
間違いを減らせる

構造体の宣言

例のcuriosity構造体は、緯度と経度の浮動小数点型フィールドを宣言
フィールドはlatlongを指している
フィールドの1つにアクセスするときは、ドット記法を使い変数名.フィールド名の形式
var xxxxx struct {

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
)

func main() {
	var curiosity struct {
		// カンマは不要
		lat  float64 // 緯度
		long float64 // 経度
	}

	// 構造体のフィールドに値を代入
	curiosity.lat = 44.02063100
	curiosity.long = 144.27342200

	fmt.Println(curiosity.lat, curiosity.long)
	fmt.Println(curiosity)
}
44.020631 144.273422
{44.020631 144.273422}

型で構造体を再利用

同じフィールド郡を持つ複数の構造体が必要なときは、構造体を独自の型として定義できる
type xxxxx struct {

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
	"fmt"
)

func main() {
	// この場合はtype
	type kmf struct {
		version      uint64
		manufacturer string
	}

	var gawain kmf // kmf(ナイトメアフレーム)型を再利用
	gawain.version = 6
	gawain.manufacturer = "Britannia"

	var gurenType02 kmf
	gurenType02.version = 7
	gurenType02.manufacturer = "Unknown"

	fmt.Println(gawain, gurenType02)
}
{6 Britannia} {7 Unkown}

構造体を複合リテラルで初期化

フィールド値: 値で初期化するのがオススメ(パターン1の方)
理由は構造体宣言で順序が変更されたり、フィールドが追加されたりしても書き換える必要がない
memo
fmt.printf("%+v", hoge)で、フィルード値も表示できる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
	"fmt"
)

func main() {
	type kmf struct {
		version  uint64
		organize string
	}

	// パターン1
	// フィルード値: 値 で初期化
	gurenType02 := kmf{version: 7, organize: "黒の騎士団"}

	// パターン2
	// フィールドを省略
	// その代り、フィールドの順序通りに値を入れる必要がある
	gurenType08ElemntsSeiten := kmf{9, "黒の騎士団"}

	fmt.Println(gurenType02)
	fmt.Println(gurenType08ElemntsSeiten)

	// %+v をすると、フィールド名も表示できる!
	fmt.Printf("%v\n", gurenType02)
	fmt.Printf("%+v\n", gurenType02)
}
{7 黒の騎士団}
{9 黒の騎士団}
{7 黒の騎士団}
{version:7 organize:黒の騎士団}

構造体のコピー

普通にコピーできる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
	"fmt"
)

func main() {
	type kmf struct {
		version  uint64
		organize string
	}

	// パターン1
	// フィルード値: 値 で初期化
	gurenType02 := kmf{version: 7, organize: "黒の騎士団"}

	// コピー
	gurenCopy := gurenType02

	gurenCopy.organize = "中国"

	fmt.Println(gurenType02)
	fmt.Println(gurenCopy)

}
{7 黒の騎士団}
{7 中国}

構造体のスライス

関連するスライスを複数作るとミスし易い
構造体を利用した方が管理が容易になるのでオススメ

悪い例

1
2
names := []string{"gurenType02", "shinkiro"{
versions := []uint64{7, 8}

構造体を利用した例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
	"fmt"
)

func main() {
	type kmf struct {
		name     string
		version  uint64
		organize string
	}

	kmfs := []kmf{
		{name: "gurenType02", version: 7, organize: "黒の騎士団"},
		{name: "shinkiro", version: 8, organize: "ブリタニア"},
		{name: "lancelotAlbion", version: 9, organize: "ブリタニア"},
	}

	fmt.Println(kmfs)
	fmt.Println(kmfs[1])
}
[{gurenType02 7 黒の騎士団} {shinkiro 8 ブリタニア} {lancelotAlbion 9 ブリタニア}]
{shinkiro 8 ブリタニア}

構造体をJSONにエンコード

注意点 フィルード名の先頭を大文字に必要がある

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
	"encoding/json"
	"fmt"
	"os"
)

func main() {
	type kmf struct {
		// フィールド名の先頭を大文字にする必要がある
		Name     string
		Version  uint64
		Organize string
	}

	kmfs := []kmf{
		{Name: "gurenType02", Version: 7, Organize: "黒の騎士団"},
		{Name: "shinkiro", Version: 8, Organize: "ブリタニア"},
		{Name: "lancelotAlbion", Version: 9, Organize: "ブリタニア"},
	}

	// ここから新要素
	bytes, err := json.Marshal(kmfs)
	exitOnError(err)

	fmt.Println(string(bytes))
}

// exitOnError は、エラーがあれば表示して終了
func exitOnError(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
[{"Name":"gurenType02","Version":7,"Organize":"黒の騎士団"},{"Name":"shinkiro","Version":8,"Organize":"ブリタニア"},{"Name":"lancelotAlbion","Version":9,"Organize":"ブリタニア"}]

まとめ

  • 構造体は複数の値を1つの単位にまとめる
  • 構造体は代入または関数に渡す時、値がコピーされる
  • 初期化するには複合リテラルが便利

感想

分かりやすくかつ、ミス防止に繋がるのでstructは利用出来る場面は積極的に利用せねば
メソッドに通じるものがあった