【Golang】メモリ、アドレス、ポインターについて

# メモリ

データやプログラムの一時的な保存場所。

メモリには「アドレス」と「メモリ領域（記憶領域）」がある

![スクリーンショット 2023-10-28 23.10.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/0f044e97-bb99-1e13-91d7-10491d54982b.png)



## アドレス

コンピュータ内のメモリにデータを保存する時に、そのデータを格納するメモリに元から付けられている番号（住所）のこと

16進数で表現される

### メモリ領域

データやプログラムが保存される領域。

メモリ領域には「データ」と「命令」が入っている。

格納場所は、紐づいているアドレスによって特定される

# Golangのメモリアドレスとは

変数の前に<font color="red">「&」</font>をつけることで、アドレスを取得することができる。

「＆」を付けなければ、メモリ領域のデータを取得してくる。

![スクリーンショット 2023-10-28 23.12.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/41931676-95f0-12d3-e722-734b64787384.png)

# Golangのポインター変数とは

「アドレスが格納された変数」の前に<font color="red">「*」</font>をつけることでポインター変数を定義できる。

## ポインターとは

メモリアドレスを格納し、そのアドレスのメモリ領域の値にアクセスできる変数。

![スクリーンショット 2023-10-28 23.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/6bfa6fa3-4377-b196-0662-a66bd7985c75.png)

# Golangのポインター型とは

型名の前に<font color="red">「*」</font>を付けたデータ型のこと

ポインタ型にはアドレスを代入する

ポインター型で定義された変数はポインター変数となり、挙動は上記と同じことをする

![スクリーンショット 2023-10-28 23.14.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/65014bae-0c17-3455-eb7b-321f88a6b2ea.png)

# 値渡し

メモリ領域の値をそのままコピーして、別のメモリ領域に格納すること。

別のメモリ領域に格納しているため、コピーしたもののアドレスは変化する


![スクリーンショット 2023-10-28 23.15.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/8f729bb1-573b-d4d7-ca2d-829993160bc9.png)
![スクリーンショット 2023-10-28 23.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/c558d715-1505-c150-e1a2-43b04281cc6f.png)
![スクリーンショット 2023-10-28 23.15.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/fc39244e-5ea5-aa8a-01df-150cdf52c331.png)



# 参照渡し

アドレスを別のメモリ領域に格納すること。

このアドレスを元に、参照元のメモリ領域の値にアクセスすることができる。

![スクリーンショット 2023-10-28 23.16.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/385a4b15-d0e2-0228-ffc4-7fac6629f9ec.png)
![スクリーンショット 2023-10-28 23.17.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/62c74913-9ccb-bb4a-348e-9cbc4f88b906.png)
![スクリーンショット 2023-10-28 23.17.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/ea9dfbda-fb26-9f30-8abd-e1d8d3257d21.png)

# メモリ領域の種類

メモリのアドレスには「低位アドレス」と「高位アドレス」がある

低い方から順番に「プログラム領域」→「静的領域」→「ヒープ領域」→「スタック領域」が割り当てられる

![スクリーンショット 2023-10-28 23.18.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/86d0c641-1401-5a22-74f9-b8d3873941c7.png)

## メモリに各種のメモリ領域が割り当てられる参考図
メモリ全体があったとして、低位アドレスから順番に上記の領域が割り当てられるようなイメージ
![スクリーンショット 2023-10-28 23.21.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/0385c77e-5797-b997-26a5-98e38fd3f52b.png)


## プログラム領域

機械語に変換されたプログラムの命令が格納される。

実行時に1行ずつ実行する。

## 静的領域

グローバル変数、定数などが配置される。

プログラム開始時に初期化され、プログラムの寿命中存在し続ける

## ヒープ領域

動的データが保持される

関数スコープに縛られずにオブジェクトを確保しておける。

・確保、解放が遅い

・寿命は自由

・サイズが大きい

・サイズが動的に決定される

・newなどで確保される

・Goコンパイラでメモリを確保できない値がヒープにエスケープされる

・GCされる

・Goコンパイラとランタイムによって、いつ使用され、いつクリーンアップされるか把握できない

## スタック領域

静的なデータが保持される

・GCを使わないため効率的

・確保、解放が早い

・寿命が短い

・サイズが小さい

・ローカル変数、引数、返り値、静的構造体、プリミティブ値など

・レキシカルスコープに紐づいたメモリが割り当てられる

・Goコンパイラが、メモリを確保する

・goroutineスタックが格納される

## 各領域まとめ

![スクリーンショット 2023-10-28 23.26.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501264/c0332cc8-6a34-292f-dd5d-11a6bd6b6492.png)


## Golangのヒープとスタック

内部的には<font color="red">優先的にスタックを使用</font>するようになっている。

## 参考資料
https://kakuyomu.jp/works/1177354054881541503/episodes/1177354054883191119

https://www.raspberrypirulo.net/entry/memory-address

https://codor.co.jp/python/program-and-memory

https://zenn.dev/rookxx/articles/golang-stack-and-heap

https://techblog.zozo.com/entry/improve-digdag-task-with-goroutine

https://developer.so-tech.co.jp/entry/2022/07/28/112845