Goアウトプット #02【マップ、構造体】

# マップ(Map)

`make(map[キーの型] 値の型)`で定義

※容量を定義する場合`make(map[キーの型] 値の型 [,容量])`

```go
func main() {
	// 容量を指定せずMapを作成
	map01 := make(map[int]string)

	// 容量を指定してMapを作成
	map02 := make(map[int]string, 5)

	fmt.Println(map01, len(map01))
	fmt.Println(map02, len(map02))
}

// -> map[] 0
//    map[] 0
```

## Mapへのアクセス

値はランダムに取得される。
└for構文のrangeを使用すれば、順番通りに取得することが可能。

```go
func main() {
	students := make(map[int]string)
	students[1] = "山田"
	fmt.Println(students, len(students))

	students[2] = "吉田"
	students[3] = "鈴木"
	fmt.Println(students, len(students))

	students[6] = "村田"
	fmt.Println(students, len(students))
}

// -> map[1:山田] 1
//    map[1:山田 2:吉田 3:鈴木] 3
//    map[1:山田 2:吉田 3:鈴木 6:村田] 4
```

```go
func main() {
	students := make(map[int]string)
	students[1] = "山田"
	students[2] = "吉田"
	students[3] = "鈴木"
	students[6] = "村田"

	for key, value := range students {
		fmt.Printf("Key=%d, Value=%s \n", key, value)
	}
}

// -> Key=1, Value=山田 
//    Key=2, Value=吉田 
//    Key=3, Value=鈴木 
//    Key=6, Value=村田
```

## キーの有無を確認する方法

`値,キーの有無 = map名[キーの値]`でキーの有無を確認する。

キーの有無は、trueかfalseで帰ってくる。

```go
func main() {
	students := make(map[int]string)
	students[1] = "山田"
	students[2] = "吉田"
	students[3] = "鈴木"

	// キーの値が存在しているか確認する変数を作成
	value01, exist01 := students[1]
	value04, exist04 := students[4]

	// キーの値が存在しているか確認
	if exist01 {
		fmt.Printf("キーあり: 値=%s, 有無=%t \n", value01, exist01)
	} else {
		fmt.Printf("キーなし: 有無=%t \n", exist01)
	}

	if exist04 {
		fmt.Printf("キーあり: 値=%s, 有無=%t \n", value04, exist04)
	} else {
		fmt.Printf("キーなし: 有無=%t \n", exist04)
	}
}
```

## ペアの削除

`delete()`関数を使用する

`delete(マップ名, キーの値)`

```go
func main() {
	students := make(map[int]string)
	students[1] = "山田"
	students[2] = "田中"
	students[3] = "吉田"

	// 2のキーを削除
	delete(students, 2)
	fmt.Println(students, len(students))
}

// -> map[1:山田 3:吉田] 2
```

## マップリテラル

マップ作成時に値指定した状態で初期化する場合、マップリテラルを使用する。

`map[int]string{キー1:値1, キー2:値2, キー3:値3, .......}`で指定をする。

```go
func main() {
	students := map[int]string{1: "山田", 2: "田中", 3: "吉田"}
	fmt.Println(students, len(students))
}

// -> map[1:山田 2:田中 3:吉田] 3
```

# 構造体（Structure）

## 構造体とは

複合要素の集合体のこと。

各要素をフィールドという。
└フィールドは先頭の1文字を大文字にすることでエクスポートすることができる。

### 構造体の宣言（変数の型）

```go
var 変数名 struct {
	フィールド名  型
	...
}
```

```go
func main() {
	// 変数の型を宣言
	var struct1 struct {
		x int
		y string
		z bool
	}

	// 構造体内で型指定宣言された変数に値を代入
	struct1.x = 100
	struct1.y = "あいうえお"
	struct1.z = false
	fmt.Println(struct1.x, struct1.y, struct1.z)
}
```

### 構造体の宣言（型）

```go
type 構造体名 struct {
	フィールド名  型
	...
}
```

```go
type Student struct {
	Number   int
	Name     string
	Gender   string
	Graduate bool
}

func main() {
	// studentとして、Student構造体のフィールドを使用できるようにする（構造体の宣言）
	var student Student

	student.Number = 123
	student.Name = "田中"
	student.Gender = "man"
	student.Graduate = false
	fmt.Println(student)
}

// -> {123 田中 man false}
```

## リテラルによる初期化

構造体宣言時に初期値を設定することができる

`構造体名{フィールド名:値, フィールド名:値, ......}`

```go
type Student struct {
	Number   int
	Name     string
	Gender   string
	Graduate bool
}

func main() {
	// 宣言と同時に初期化を行う
	student001 := Student{Number: 1, Name: "田中", Gender: "female", Graduate: false}
	student002 := Student{Number: 2, Name: "吉田", Gender: "male", Graduate: true}
	fmt.Println(student001)
	fmt.Println(student002)
}

// -> {1 田中 female false}
//    {2 吉田 male true}
```

## 埋め込みと匿名フィールド

構造体に他の構造体を埋め込むことで、継承と似た構造を作ることができる（埋め込み）

埋め込む構造体は、埋め込む先の構造体で型名のみ記述する。
└型名のみのフィールドを、「匿名フィールド」という。

```go
type 埋め込まれる構造体 struct {
	.....
}

type 埋め込む構造体 struct {
	.....
	埋め込まれる構造体(匿名フィールド)
}
```

```go
type EmbededAddress struct {
	City         string
	Municipality string
	Address      string
}

type EmbededStudent struct {
	Number   int
	Name     string
	Gender   string
	Graduate bool
	// 構造体の埋め込み（匿名フィールド）
	EmbededAddress
}

func main() {
	var student01 EmbededStudent

	student01.City = "東京都"
	student01.Municipality = "新宿区新宿"
	student01.Address = "1-11-1"
	student01.Number = 1234
	student01.Name = "田中"
	student01.Gender = "female"
	student01.Graduate = false

	fmt.Println(student01)
}

// -> {1234 田中 female false {東京都 新宿区新宿 1-11-1}}
```