[The Go Programming Language Specification] Pointer

# Go
Golangのspecificationの日本語訳と、ちょっとした遊びぐらいのコードを載せていく感じで進めようと思うので、
すでにGolangでコードを書いている人にはつまらないかもしれないです

また、間違っている部分があればぜひご指摘いただけると嬉しいです🙇‍♂️

### 想定する読者層
- Golang初めてそこまで期間が経っていない
- 英語の公式読むの辛い
    - https://golang.org/ref/spec


## Pointer types
本記事は公式のドキュメントを参考にしています

- https://golang.org/ref/spec#Pointer_types

### Pointer とは？
**Pointer はその変数のメモリ上のアドレスを示します**

は？と大学時代の私はなりC言語のことが嫌いになって一度プログラミングを挫折しました
Pointerを使って返却されたアドレスをみてシンプルに拒否反応が出ました
ちなみに↓のような値でした

```text
0xc0000a0008
```

結局その後、PHP, Python, Rubyと様々な（動的）言語を学び、 Golang を学ぶ必要が出て久しぶりに Pointer に出会いました
いろんな言語を学んでみて思いますが、 Pointer も他の文法と同じようにただ淡々と学ぶことができていれば大学の時に挫折に済んだのかなと思っています(ちなみに、ポインタの概念はどの言語にも存在していますが、本記事では取り上げません)

という余談は置きつつ、Pointer の宣言とかどういう使い方があるのかとかを説明しています
私の説明で ？ となってしまったら申し訳ないですが、質問していただいたり他の方の記事も参考にしていただけたらと思います

### Pointer の宣言方法
Pointerは以下のようにして型の前に `*` をつけて宣言します

```golang
var p *int
var p *string
```

初期化していない状態では Pointer には nil が設定されます

```golang
var p *int
fmt.Println(p) // = nil
```

普通に宣言した変数からアドレスを取り出すこともでき、pointerで宣言した変数には`&`を使って格納します

```golang
i := 10
fmt.Println(&i) // = 0xc0000aa000

var p *int
p = &i
fmt.Println(p)  // = 0xc0000aa000
```

pointer で宣言した変数の実体は `*` で取得することができます (pointer を宣言した時の `*` と最初はごっちゃになってしまうので使って慣れましょう)

```golang
fmt.Println(*p) // 10
```

ちなみにgolangではnewを使って、動的にメモリの確保を行うこともできます

```golang
p := new(int)
fmt.Println(p) // = 0xc0000aa000
```

## サンプル
おそらく Pointer の宣言とアドレス、実体値を取り出せるようになっただけでは`だから何？`という気持ちになります（私はなりました）
c言語をやったことがあるひとは知っていると思いますが、`ポインタ(参照)渡し`と`値渡し`の２パターンを知っていると使いどころが少しわかってくるのではないかと思っています

正直、言葉だけで考えようとすると意味わからなくなってプログラム（ポインタ）のことが嫌いになってしまうかもしれないので
ただ、淡々と文法を覚えるかのようにサンプルを書いて覚えてしまいましょう

### 値渡し
値渡しは、pointerではなく宣言した変数を関数に渡した時に、その変数のコピーが渡されることです
そしてその変数のコピーは引数で渡した変数とは異なるアドレスに作成されます

```golang
package main

import "fmt"

func main() {
	var s = "James"
	fmt.Printf("%v address is %p\n", s, &s)
	Greeting(s)
}

func Greeting(s string) {
	fmt.Println("Hello, " + s)
	fmt.Printf("%v address is %p\n", s, &s)
}
```
```text
James address is 0x40c138
Hello, James
James address is 0x40c150
```

関数に渡す前に `s` で宣言した変数のアドレスは `0x40c138` でしたが、
関数に渡された後の `s` のアドレスは `0x40c150` でした

つまり Greeting に渡される前の `s` と Greeting に渡された `s` は全くの別物であるということです
https://play.golang.org/p/WcYtv-7BKHa

なので、関数内で `s` の中身を別の文字列に変えようが、関数に渡される前の `s` には全く影響がありません

```golang
package main

import "fmt"

func main() {
	var s = "James"
	fmt.Printf("%v address is %p\n", s, &s)  // 1
	Greeting(s)
	fmt.Printf("%v address is %p\n", s, &s)  // 4
}

func Greeting(s string) {
	fmt.Println("Hello, " + s)               // 2
	fmt.Printf("%v address is %p\n", s, &s)  // 3
	s = "Hoge"
}

```

```text
James address is 0x40c138
Hello, James
James address is 0x40c150
James address is 0x40c138
```
https://play.golang.org/p/-ezTbBtuGxB

play ground で実行して確かめて遊んでみると、理解度が増すかもしれません

### ポインタ渡し
次に、本記事のメインであるポインタを使った方法で関数に値を渡すようにしてみましょう
大事な点は二つあります
- 関数内外での変数のアドレス
- Greeting 後での変数の中身
以上２点に気をつけて見てみましょう

```golang
package main

import "fmt"

func main() {
	var s = "James"
	fmt.Printf("%v address is %p\n", s, &s) // 1
	Greeting(&s)
	fmt.Printf("%v address is %p\n", s, &s) // 4
}

func Greeting(s *string) {
	fmt.Printf("Hello, %v\n", *s)           // 2
	fmt.Printf("%v address is %p\n", *s, s) // 3
	*s = "Hoge"
}
```

```text
James address is 0x40c138
Hello, James
James address is 0x40c138
Hoge address is 0x40c138
```
https://play.golang.org/p/9XeMeSmXUhO

いかがでしょう、２つの点に気をつけながら見てみるとわかりやすかったのではないでしょうか
少しわかりにくい言い方をするのであれば、ローカル変数を別の関数上で書き換え可能であるという感じでしょうか

ここまで試した方は疑問に思っているはずです
**`わざわざ関数内で変数の中身を変えずに、mainのなかで変えれば良くないか`**

ポインタのメリットは以下の点などが挙げられます
- 省メモリ化
- 高速化

これらについては、本記事よりもとてもわかりやすい記事を書いてくださっている方がいるのでそちらを読んでみてはいかがでしょうか
http://pg-kura.hatenablog.com/entry/20120616/1339856279

それでもよくわからんという方は質問したり、他の記事も併せて読んでみてください