## What — 内部表現と外部表現の変換
エンコードとは、プログラム内部のデータ(Go の構造体など)を、送信・保存できる**バイト列**(JSON 文字列など)に変換すること。デコードはその逆で、受け取ったバイト列を内部のデータ構造に戻すこと。
なぜ変換が要るかというと、メモリ上の構造体はそのプロセスの中でしか意味を持たないから。ネットワークの向こうの相手やファイルに渡すには、言語に依存しない共通形式へ直す必要がある。
```mermaid
flowchart LR
J["外部形式<br>JSON バイト列"] -->|"デコード(受け取った直後)"| S["内部形式<br>Go の構造体"]
S -->|"エンコード(送る直前)"| J
```
覚え方は接頭辞で持つ:**en- は「中に入れる」**(encase・enclose の仲間)=データを符号(code)に詰める。de- は「解く」(decipher・decompress の仲間)=符号を解いて取り出す。
## How — ingestion は「入口でデコード、出口でエンコード」
データ取り込み(ingestion)の処理は、外部 API の JSON をデコードして構造体で加工し、次の送信先へエンコードして渡す、という往復で書ける。
```go
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
// デコード:API レスポンスのバイト列 → 構造体
var u User
if err := json.Unmarshal(body, &u); err != nil {
return err
}
// エンコード:加工した構造体 → 次へ送るバイト列
out, err := json.Marshal(u)
```
バッククォートの `json:"id"` は構造体タグで、JSON のキーと Go のフィールドの**対応表**になる。Go 側はフィールド名が大文字始まり(公開)でないと変換対象にならない点もセット。
> [!warning]
> `json.Unmarshal` は、タグとキー名が一致しないフィールドを**エラーにせずゼロ値のまま**通す。ingestion だと「エラーは出ないのに値が全部空」という形で現れるので、取り込み結果が空のときはまずタグの typo を疑う。
> [!success]
> エンコード=内部→外部形式、デコード=外部→内部。ingestion のコードは「入口で Unmarshal、出口で Marshal」の往復で読める。
## 関連
- [[Go]]
- [[Goスライスの len・cap・nil]] — nil スライスが JSON でどう出るかの話。エンコード時の隣の落とし穴