Go言語を真剣に勉強してみた〜基本構文編④（ポインタ、構造体）〜

# はじめに

おはようございます。こんにちは。こんばんは。
Watatakuです。
本日の内容は「Goのポインタ、構造体について改めて勉強しました。」と言う内容でやっていきます。

自分と同じくポインタの概念が存在しない言語から始めた人にとっては、なかなかとっつきにくいものだと思います。
なのでこの機会に一緒に理解を深めていきましょう。

「Go言語を真剣に勉強してみた〜基本構文編①（変数、定数、条件分岐、繰り返し処理）〜」については[こちら](https://qiita.com/watataku/items/f12163ade0d820d00bba)から。
「Go言語を真剣に勉強してみた〜基本構文編②（配列）〜」については[こちら](https://qiita.com/drafts/50de84b191f73d281be9)から。
「Go言語を真剣に勉強してみた〜基本構文編③（関数）〜」については[こちら](https://qiita.com/watataku/items/79f5e49d08000838150d)から。

# ポインタ

そもそもポインタとはなんぞやと言う話からします。
ポインタとは、**メモリのアドレス情報**のことです。

## 変数のアドレス取得方法

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

## ポインタ型変数

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

```go
func main() {
    var hoge int = 10//int型の変数
    var bow *int = &hoge //int型へのポイント型

    fmt.Println(hoge) //=> 10
    fmt.Println(bow) //=> 0x10414020   
}
```

<font color="red">*※初期値が指定されていない場合、Go 言語のポインタは nil (nil ポインタ) に初期化されます*</font>

## ポインタ型変数の中身へのアクセス方法

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

```go
func main() {
    var hoge int = 10
    var bow *int = &hoge
    fmt.Println(*bow) //=> 10
}
```

[参照](https://qiita.com/Sekky0905/items/447efa04a95e3fec217f)
[実際のコード](https://github.com/watataku8911/golang-basic/blob/master/pointer.go)

# 構造体

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

## 構造体の定義

```
type 構造体名 struct {
   フィールド名 データ型
}
```

<font color="red">※Goの場合、大文字から始まる名前は、他のパッケージからアクセス可能となります。
一方、小文字で始まる名前の場合、他のパッケージからアクセス不可能です(カプセル化)。同じパッケージ内であれば小文字でもアクセス可能です。</font>

## 構造体の初期化
構造体の初期化方法は複数あります.

- ①変数定義後にフィールドを設定する方法
- ②{} で順番にフィールドの値を渡す方法
- ③フィールド名を``：``で指定する方法
- ④初期化関数を作成することで初期化をする

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

```go
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
}
```

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

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

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

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

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

func main(){
  sam := Person{age: 15, firstName: "Sam"}
  fmt.Println(sam.firstName, sam.age) //=>Sam 15
}
```

④初期化関数を作成することで初期化をする

```go
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
}
```

[実際のコード](https://github.com/watataku8911/golang-basic/blob/master/struct.go)

##メソッド
Goの構造体にはもう１つ便利な機能があります。それがメソッドです。
下記構文でメソッドを定義することができます。

```
func (レシーバ名  レシーバの型) 関数名(引数) (戻り値) {
    //処理
}
```
では上記で作った、User構造体にメソッドを定義して使ってみましょう。

```golang
func (u User) greet() string {
    return "hello," + u.Name;
} 

var user *User = newUser("taro", 30, "hoge@example.ac.jp")
user.greet()
```
greetメソッドではレシーバーにUserを指定しています。メソッドはフィールドと同じように、「.」 を使ってアクセスします。
メソッドではレシーバ(User)のもつフィールドにアクセスすることが可能です。
また、同じ名前のメソッドがあっても、レシーバが異なればメソッドは別のものとして扱われるので注意してください。

以上。
もし何か間違っている等のご指摘があればご連絡ください。
長くなりましたが、最後まで読んで頂きありがとうございました。
次回は「Go言語を真剣に勉強してみた〜パッケージ編〜」です。

よろしければ、[Go言語を真剣に勉強してみた〜環境構築編〜](https://qiita.com/watataku/items/c2b25ace1aeaaf0b75c0)もご覧ください。