Goのポインタの簡単な例

## はじめに
Go言語での実体とポインタ、アドレスの扱いについて整理します。


## 値渡しとポインタ渡しの違い
Go言語での実体とポインタ、アドレスの扱いについて、簡単な例を示します。
以下の例では、関数に値を渡す際にコピーが発生する場面と、ポインタを使って直接メモリアドレスを参照する場面を比較しています。

### 実体のコピーが発生する例
<b>値渡し（コピー渡し）</b>
```go
package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

// passByValue はPersonのコピーを受け取る
func passByValue(p Person) {
	p.Age = 30 // この変更はコピーにのみ影響する
	fmt.Println("Inside passByValue:", p)
}

func main() {
	p := Person{Name: "Alice", Age: 25}
	fmt.Println("Original person:", p)

	passByValue(p) // 関数に値を渡す（コピーが発生する）
	fmt.Println("After passByValue:", p) // 元のPersonオブジェクトは変更されない
}
```
```
Original person: {Alice 25}
Inside passByValue: {Alice 30}
After passByValue: {Alice 25}
```

このコードでは、`passByValue` 関数が `Person` 型のオブジェクトを値渡しで受け取るため、元の `Person` オブジェクト (`p`) は変更されません。関数内での変更はコピーされたオブジェクトにのみ影響します。

### ポインタを使ってアドレスを直接参照する例
<b>ポインタ渡し(直接渡し)</b>
```go
package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

// passByPointer はPersonへのポインタを受け取る
func passByPointer(p *Person) {
	p.Age = 30 // ポインタを通じて元のオブジェクトを変更する
	fmt.Println("Inside passByPointer:", *p)
}

func main() {
	p := Person{Name: "Alice", Age: 25}
	fmt.Println("Original person:", p)

	passByPointer(&p) // 関数にポインタを渡す（アドレスを参照する）
	fmt.Println("After passByPointer:", p) // 元のPersonオブジェクトが変更される
}
```

```
Original person: {Alice 25}
Inside passByPointer: {Alice 30}
After passByPointer: {Alice 30}
```

この例では、`passByPointer` 関数が `Person` 型のオブジェクトへのポインタを受け取るため、関数内での変更が元のオブジェクトに反映されます。


## 整理
Go言語での値の渡し方がどのように影響するかがわかります。
以下の点がポイントです。
- 値渡しではオブジェクトのコピーが作成されます。
- ポインタ渡しではオリジナルのオブジェクト自体が変更されます。

はい、その理解で正しいです。Go言語において、「値渡し」と「ポインタ渡し」の違いを整理しましょう：

### 値渡し（コピー渡し）
- 関数に値を渡す際には、その値の**コピー**が作成されます。
- コピーされた値は元のデータとは独立しており、関数内でコピーに変更を加えても、元のデータには影響しません。
- 主に基本的なデータ型（整数、浮動小数点数、ブール値など）や、構造体や配列などの複合データ型がこの方法で渡される場合、その全体がコピーされます。

### ポインタ渡し（直接渡し）
- ポインタ渡しでは、関数に値のメモリアドレス（ポインタ）が渡されます。
- この方法では、関数がポインタを通じて直接元のデータを参照し、変更することができます。
- ポインタ渡しは特に大きなデータ構造や、関数外でも変更を反映させたい場合に有用です。

両者の選択は、パフォーマンスの考慮（大きなデータ構造のコピーを避けたい場合など）や、関数呼び出し後の状態の管理（元のデータを変更するかどうか）に依存します。値渡しは安全性が高く、副作用が少ないため、データの意図しない変更を防ぎたい場面で適しています。一方、ポインタ渡しは効率的で、複数の関数間でのデータの変更を容易にします。


## 他言語の場合
せっかくなのでポインタ制御を他ではどうしているか言及してみます。

PHPやJavaでは、ポインタ渡しを実現しています。
よってパフォーマンスは高いです。

PHPやJavaとGoを比較すると、それぞれの言語設計の違いが、利便性、パフォーマンス、安全性に異なる影響を与えます。以下のポイントでそれぞれの特徴をまとめます。

### PHPとJava
- **利便性**：PHPやJavaでは、オブジェクトが自動的に参照として扱われるため、開発者は明示的なポインタ操作を意識する必要がありません。これにより、特にオブジェクト指向プログラミングにおいてコードが直感的で書きやすくなります。
- **パフォーマンス**：JavaはJVM（Java Virtual Machine）上で実行され、JIT（Just-In-Time）コンパイルを通じて高速化されますが、ネイティブコンパイルされた言語に比べると一般に少し遅い傾向があります。PHPは通常、リクエストごとにインタープリタがスクリプトを解釈するため、さらに遅くなりがちです。
- **安全性**：両言語ともメモリ管理を抽象化し、ガベージコレクションを提供しています。これにより、メモリリークやポインタ関連のバグを減少させることができますが、これが結果としてランタイムコストを増加させることもあります。

### Go
- **利便性**：Goはポインタをサポートしており、ポインタ操作が必要な場合があります。これにより、C言語のような低レベル言語の柔軟性がありますが、ポインタを不適切に扱うとバグの原因にもなりえます。
- **パフォーマンス**：Goはコンパイル言語であり、生成されるバイナリは直接マシンコードに変換されるため、実行速度が非常に高速です。これは特に並行処理やシステムプログラミングでの利点となります。
- **安全性**：Goはポインタを使いますが、ポインタ算術は許されていません。この制限により、ポインタを使用しつつも、C言語ほどのリスクは抑えられています。また、強力な型システムと明確なエラーハンドリングが、さらに安全性を高めています。

### 結論
PHPやJavaが「使いやすさ」を重視しているのに対し、Goは「パフォーマンス」と「制御の精度」に優れていると言えます。Goは低レベルの制御を必要とするアプリケーションや、高速な実行が求められる環境に特に適しています。一方で、PHPやJavaはプログラマがメモリ管理から一歩離れてビジネスロジックに集中できる環境を提供します。それぞれの言語が持つこれらの特性を理解することで、プロジェクトの要件に最も適した技術選択が可能になります。

## 参考記事
https://recursionist.io/learn/languages/go/complex/pointer

https://qiita.com/Sekky0905/items/447efa04a95e3fec217f

https://qiita.com/hiroaki-u/items/da7694ecffccbb49a139