構造体
関係のある複数の値を1つのグループにまとめる
間違いを減らせる
構造体の宣言
例のcuriosity
構造体は、緯度と経度の浮動小数点型フィールドを宣言
フィールドはlat
、long
を指している
フィールドの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
は利用出来る場面は積極的に利用せねば
メソッドに通じるものがあった