【Go】基本文法③(ポインタ・構造体)

# 概要
[A Tour of Go](https://tour.golang.org/)の順番に沿ってGoの基本で個人的に学習したことをまとめています。

| No | 記事 |
|------|---------|
|    1  |   [【Go】基本文法①(基礎)](https://qiita.com/k-penguin-sato/items/1d0e1c6b4bf937996cd3)|
|    2  |   [【Go】基本文法②(フロー制御文)](https://qiita.com/k-penguin-sato/items/31b45fd3914797b654f0)|
|    3  |  __〜〜【Go】基本文法③(ポインタ・構造体)「今ココ」〜〜__|
|    4  |  [【Go】基本文法④(配列・スライス)](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)|
|    5  |   [【Go】基本文法⑤(Maps・ Range)](https://qiita.com/k-penguin-sato/items/a320072fa09502bde3e9)|
|    6  |    [【Go】基本文法⑥(インターフェース)](https://qiita.com/k-penguin-sato/items/885a61d819cc431304f5)     |
|    7  |     [【Go】基本文法⑦(並行処理)](https://qiita.com/k-penguin-sato/items/5b09fa89d8d231bcdac8)    |
|    8  |    [【Go】基本文法総まとめ](https://qiita.com/k-penguin-sato/items/deaeab18aa416496e273)     |

今回はポインタと構造体に焦点を当てて学習しました。

# ポインタ

### ポインタとは？
ポインタはメモリのアドレス情報のことです。
詳しい説明は以下のリンクがとても参考になりました。

【参考】

- [Goで学ぶポインタとアドレス](https://qiita.com/Sekky0905/items/447efa04a95e3fec217f)
- [C言語のポインタきらい](https://qiita.com/bugdasi/items/7856931f4cacf2c5b743)

```Golang
package main

import "fmt"

func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(var1) //=> 10
    fmt.Println(var2) //=> 0x10414020   
    fmt.Println(*var2) //=> 10
}
```

### 変数のアドレス取得方法
Goでは`&` を用いることで変数のアドレスの取得が可能です。
例えば `&var1` で変数 `var1` のアドレスを取得することが可能です。

```Golang
func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(var1) //=> 10
    fmt.Println(var2) //=> 0x10414020   
}
```
上記では変数 `var1` のアドレスを ポインタ型変数`var2` に入れてその値(0x10414020)を表示しています。
次にポインタ型変数とは何か理解します。

### ポインタ型とは？
__メモリー上のアドレスを記憶する変数の型のこと__ です。
サンプルコード上の `*int` がポインタ型を示します。

```Golang 
var var2 *int = &var1
```

### ポインタ型変数とは？
__ポインタ型で宣言された変数のこと__ です。
つまり、__メモリ上のアドレスを値として入れられる変数のこと__ です。
ポインタ型にしたい変数に `*` をつけて宣言します。

```Golang
var var1 int      //int型
var var2 *int    //int型へのポイント型
```
サンプルコード上の `var2` がポインタ型変数を示します。
初期値が指定されていない場合、Go 言語のポインタは `nil (nil ポインタ)` に初期化されます。

【参考】[ポインタ型変数とは](https://qiita.com/kazuooooo/items/3fd14ca5b8827c60a4fe)


### ポインタ型変数の中身へのアクセス方法
ポインタ型変数名の前に `*` をつけることで変数の中身へのアクセスが可能です。
例えば `*var2` とすることで `var2`　の値の参照が可能です。

```Golang
func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(*var2) //=> 10
}
```

# Structs(構造体)

### 構造体とは？
Goにはオブジェクト指向言語におけるclassというものは存在しません。
似た役割として関連する情報をひとまとめにする `struct（構造体）` が使用されます。

### 構造体の定義方法
構造体は下記のように `type` と `struct` を使用して定義します。

```Golang
package main 

import "fmt"

type Person struct {
   firstName string 
   age int
}
```

### 構造体の初期化方法
構造体の初期化方法は複数存在します。

- ①変数定義後にフィールドを設定する方法
- ②`{}` で順番にフィールドの値を渡す方法
- ③フィールド名を `：` で指定する方法

上から順に初期化の方法を確認します。

①変数定義後にフィールドを設定する方法

```Golang
type Person struct {
   firstName string 
   age int
}

func main(){
  var mike Person
  mike.firstName = "Mike"
  mike.age = 20
  fmt.Println(mike.firstName, mike.age) //=> Mike 20
}
```

②`{}` で順番にフィールドの値を渡す方法

```Golang
type Person struct {
   firstName string 
   age int
}

func main(){
  bob := Person{"Bob", 30}
  fmt.Println(bob.firstName, bob.age) //=>Bob 30
}
```

③フィールド名を `：` で指定する方法

```Golang
type Person struct {
   firstName string 
   age int
}

func main(){
  sam := Person{age: 15, firstName: "Sam"}
  fmt.Println(sam.firstName, sam.age) //=>Sam 15
}
```
また以下のように初期化関数を作成することで初期化をすることも一般的に行われます。

```Golang
type Person struct {
   firstName string 
   age int
}

func newPerson(firstName string, age int) *Person{
     person := new(Person)
	 person.firstName = firstName
	 person.age = age
	 return person
}

func main(){
  var jen *Person = newPerson("Jennifer", 40)
  fmt.Println(jen.firstName, jen.age) //=>Jennifer 40
}　
```
### 構造体とポインタ
`struct` のフィールドは、`struct` のポインタを通してアクセスすることもできます。

```Golang
package main

import "fmt"

type Person struct {
  firstName string
  age int
}

func main() {
	tim := Person{"Tim", 25}
	person1 := &tim
	(*person1).age = 25
	person1.age = 53 //shortcutでp.Xと書くことも出来る
	fmt.Println(person1) //=> {Tim 53}
}
```

### 構造体でのメソッドの定義
Goにはクラスと言う概念は存在しませんが、構造体内にメソッド `method` を定義できます。
__普通の関数と違うのはレシーバ引数の部分だけです。__

メソッドは以下の様に定義することができます。

```Golang
func (<レシーバ引数>) <関数名>([引数]) [戻り値の型] {
    [関数の本体]
}
```

実際に `Person` という構造体に対して `intro` というメソッドを定義してみます。

```Golang
type Person struct {
   firstName string 
   age int
}

func (p Person) intro(greetings string) string{
    return greetings + " I am " + p.firstName
}

func main(){
  bob := Person{"Bob", 30}
  fmt.Println(bob.intro("Hello")) //=> Hello I am Bob
}
```
上記の例では `intro` メソッドは `p` という名前の `Person` 型のレシーバを持つことを意味しています。

### 構造体の埋め込み
上記で何度も記した通り、Goはオブジェクト指向言語の様なクラスを持ちません。
ですのでクラスの継承も存在しません。
そこで継承に似た機能として構造体の埋め込みがあります。

```Golang
package main 

import "fmt"

type Person struct {
   firstName string 
}

func (a Person) name() string{ //Personのメソッド
    return a.firstName
}

type User struct {
     Person
}

func (a User) name() string { //Userのメソッド
    return a.firstName
}

func main(){
  bob := Person{"Bob"}
  mike := User{}
  mike.firstName = "Mike"
  
  fmt.Println(bob.name()) //=> Bob
  fmt.Println(mike.name()) //=> Mike
}
```

# 参考
[My Jorney of Go③](https://k-blog0130.herokuapp.com/posts/16)
[C言語のポインタきらい](https://qiita.com/bugdasi/items/7856931f4cacf2c5b743)
[Goで学ぶポインタとアドレス](https://qiita.com/Sekky0905/items/447efa04a95e3fec217f)
[メソッドの定義方法](https://blog.y-yuki.net/entry/2017/05/05/000000)
[ポインタ型変数とは](https://qiita.com/kazuooooo/items/3fd14ca5b8827c60a4fe)
[Goのinterface/structの埋め込み](https://www.sambaiz.net/article/50/)
[お気楽 Go 言語プログラミング入門](http://www.geocities.jp/m_hiroi/golang/abcgo08.html)