Go 基本文法【ポインタ・構造体・配列編】

## はじめに
今回はGoの基本文法である<b>「ポインタ・構造体・配列」</b>についてです。

## 目次
1. [Pointers ： ポインタ](#pointers--ポインタ)
2. [Structs ： 構造体](#structs--構造体)
3. [Embedded Structs ： 構造体の埋め込み(継承)](#embedded-structs--構造体の埋め込み継承)
4. [Arrays ： 配列](#arrays--配列)
5. [参考文献](#参考文献)

## Pointers ： ポインタ
ポインタとは、値のメモリアドレスのことです。
変数の型の前に```*```が付くものは<b>ポインタ型変数</b>、付かないものは変数となります。
```golang
var 変数名 *型
```
変数には格納されている値とは別にアドレス情報を持っています。いわば<b>変数の住所</b>ですね。
Goでは```&```を使って、変数のアドレスを取得することができます。
```golang:main.go
package main

import "fmt"

func main() {
	// string 型の変数 str
	var str string = "ポインタのテスト"
	
	// string 型へのポインタ型 str_pointer 変数に str のアドレスを格納
	var str_pointer *string = &str

	fmt.Println(str) // => ポインタのテスト
	fmt.Println(str_pointer) // => 0x000096210
}
```
ポインタ型変数名の前に```*```をつければ、変数の値を取得することができます。
```*```をつければアドレス、つけなければ値へのアクセスとなります。
```golang:main.go
fmt.Println(*str_pointer) // => ポインタのテスト
```
主な用途は、引数やレシーバを経由する関数内で書き換えたい時です。
Goでは、書き換え対象はポインタとして渡す必要があります。
```golang:main.go
package main

import "fmt"

type Pointer struct{ value int }

// ポインタ型でないため、+5されない(書き換え不可)
func (h Pointer) Not_Pointer(v int) {
	h.value = v + 5
}

// ポインタ型のため、+5される(書き換え可)
func (h *Pointer) Pointer(v int) {
	h.value = v + 5
}

func main() {
	var h Pointer // データ書き換え対象の変数

	h.Not_Pointer(0)
	fmt.Printf("Not_Pointer:%v\n", h.value) // => Not_Pointer:0

	h.Pointer(0)
	fmt.Printf("Pointer:%v\n", h.value) // => Pointer:5
}
```
## Structs ： 構造体
Goにクラスは存在しません。
構造体はクラスと似た役割を果たし、関連情報をひとまとめにすることができます。

構造体は、```type```と```struct```を使って定義(個別・複数どちらでも定義可)します。
構造体はフィールドの集まりです。
```golang
type 構造体名 struct {
    フィールド名 型
    フィールド名 型
}
```
フィールドへは```.```を使ってアクセスします。
```golang
構造体のポインタ名.構造体のフィールド名 = 1
```
構造体の初期化方法は複数あります。
　①変数定義後にフィールドを設定する方法
　②```{}```内で順番にフィールドの値を渡す方法
　③フィールド名を```：```で指定する方法
```golang
// ①
type People struct {
   name string 
   age int
}

func main(){
  var jack People
  jack.name = "Jack"
  jack.age = 20
  fmt.Println(jack.name, jack.age) // => Jack 20
}
```
```golang
// ②
func main(){
  jack := People{"Jack", 20}
  fmt.Println(jack.name, jack.age) // => Jack 20
}
```
```golang
// ③
func main(){
  jack := People{age: 20, name: "Jack"}
  fmt.Println(jack.name, jack.age) // => Jack 20
}
```
以下のように、初期化関数を作成し初期化することも一般的のようです。
```golang
func newPerson(name string, age int) *People{
     person := new(People) // 初期化する
	 person.name = name // name フィールドへ値を代入
	 person.age = age // age フィールドへ値を代入
	 return person
}

func main(){
  var jack *People = newPerson("Jack", 20)
  fmt.Println(jack.name, jack.age) // => Jack 20
}
```
Goにはクラスの概念がないですが、構造体内でメソッドを定義することができます。
メソッドの定義方法は以下の通りです。<b>関数と異なる点はレシーバ引数の部分</b>だけです。
```golang
func (レシーバ引数) 関数名(引数) 戻り値の型 {
    関数の本体
}
```
```golang:main.go
package main

import "fmt"

type People struct {
   name string 
   age int
}

// メソッド定義 ： Poeple という構造体に対して introduction というメソッドを定義
// introduction メソッドは p という名前の People 型のレシーバを持つ
func (p People) introduction(greetings string) string{
    return greetings + " I am " + p.name
}

func main(){
  jack := People{"Jack", 20}
  fmt.Println(jack.introduction("Hello")) // => Hello I am Jack
}
```

## Embedded Structs ： 構造体の埋め込み(継承)
他の言語にあるクラス継承に似た機能として<b>構造体の埋め込み</b>があります。
1つの構造体を別の構造体へ埋め込むことが可能です。
```golang:main.go
package main

import "fmt"

// 構造体宣言
type character struct {
	name string
	age  int
}

func main() {
	// 構造体へデータセット
	c := character{
		name: "Jack",
		age:  20,
	}
	
	// 構造体自体を出力
	fmt.Println(c) // => {Jack 20}
	
	// 構造体のフィールドデータを出力
	fmt.Println(c.name, c.age) // => Jack 20
}
```

## Arrays ： 配列
配列は、同じ型を持つ値（要素）を並べたものです。
Goにおける配列は<b>固定長配列</b>のため、最初に宣言した配列サイズは変更できません。

配列の宣言方法は以下の通りです。
　① var 変数名 [長さ]型
　② var 変数名 [長さ]型 = [大きさ]型{初期値1, 初期値n} 
　③ 変数名 := [...]型{初期値１, 初期値n}

```golang
// ①
func main(){
   var arr[2] string 
       arr[0] = "Hello World"
       arr[1] = "Go"
       fmt.Println(arr[0], arr[1]) //=> Hello World
       fmt.Println(arr) //=> [Hello World]
}
```
```golang
// ②
func main(){
   var arr[2] string = [2]string {"Hello", "Go"}
       fmt.Println(arr[0], arr[1]) //=> Hello Go
       fmt.Println(arr) //=> [Hello Go]
}
```
```golang
// ③
// 要素数は省略可、要素数は自動カウントしている
func main(){
     arr := [...] string{"Hello", "Go"}
     fmt.Println(arr[0], arr[1]) //=> Hello Go}
     fmt.Println(arr) //=> [Hello Go]
}
```

## 参考文献
<a href="https://go-tour-jp.appspot.com/">A Tour of Go</a>
<a href="https://qiita.com/Sekky0905/items/447efa04a95e3fec217f">Goで学ぶポインタとアドレス</a>
<a href="https://golang.hateblo.jp/entry/golang-how-to-use-struct">Go言語(golang) 構造体の定義と使い方</a>
<a href="https://zenn.dev/marietty/articles/b3e0efd8e92078">[Go]構造体を学ぶ</a>
<a href="https://golang.keicode.com/basics/go-array.php">Go 言語の配列</a>