init 251117

This commit is contained in:
2025-11-17 23:25:36 +09:00
commit 734f3af161
18 changed files with 1761 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
# Go 언어와 JSON 다루기
Go 언어에서 JSON 데이터를 다루는 방법을 배워봅시다.
Go 표준 라이브러리에는 JSON 데이터를 처리하기 위한 `encoding/json` 패키지가 포함되어 있습니다. Go는 구조체 태그(Struct Tag)를 사용하여 Go 구조체와 JSON 필드를 손쉽게 매핑할 수 있는 기능을 제공합니다. 이 태그는 Go 구조체를 JSON으로 변환하거나, JSON을 Go 구조체로 변환하는 과정을 제어합니다. 이 과정을 각각 Marshaling과 Unmarshaling이라고 부릅니다.
## `Marshal()`과 `Unmarshal()` 이해하기
**Marshaling**과 **Unmarshaling**은 Go 구조체로 JSON 데이터를 다룰 때 핵심적인 과정입니다.
- **Marshaling**: Go 구조체(메모리 상의 데이터)를 JSON 문자열(텍스트 데이터)로 변환하는 과정입니다. 주로 API 응답으로 JSON을 보내거나, 데이터를 파일로 저장할 때 사용됩니다.
- **Unmarshaling**: JSON 문자열을 Go 구조체로 변환하는 과정입니다. 주로 외부 API로부터 받은 JSON 데이터를 다루거나 파일에서 데이터를 읽어올 때 사용됩니다.
> **가장 흔히 겪는 문제**: JSON과 Go 구조체 간 변환 시 가장 흔한 버그는 구조체의 필드명을 소문자로 시작하여 발생하는 문제입니다. `encoding/json` 패키지가 구조체의 필드에 접근하려면, 해당 필드는 **반드시 대문자로 시작해야 합니다 (Exported field)**. Marshaling 또는 Unmarshaling이 제대로 동작하지 않는다면, 가장 먼저 구조체 필드명이 대문자로 시작하는지 확인해 보세요.
# 코딩 예제
아래 `encodeDecode.go` 코드는 간단한 예제를 통해 JSON 레코드의 Marshaling과 Unmarshaling 과정을 보여줍니다.
```go
package main
import (
"encoding/json"
"fmt"
)
// UseAll 구조체는 JSON 데이터와 매핑됩니다.
type UseAll struct {
Name string `json:"username"`
Surname string `json:"surname"`
Year int `json:"created"`
}
```
구조체 필드 옆의 `` `json:"..."` `` 부분을 **구조체 태그**라고 부릅니다. 이 태그는 각 필드가 JSON 데이터에서 어떤 키(key)와 매핑되는지를 명시합니다.
- `Name` 필드는 JSON에서 `username` 키와 매핑됩니다.
- `Surname` 필드는 `surname` 키와 매핑됩니다.
- `Year` 필드는 `created` 키와 매핑됩니다.
이 태그 정보는 Marshaling과 Unmarshaling 과정에서 사용되며, 이 외에는 `UseAll`을 일반적인 Go 구조체처럼 사용하면 됩니다.
```go
func main() {
// Marshaling할 구조체 인스턴스 생성
useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}
// Go 구조체를 JSON 바이트 슬라이스로 Marshaling합니다.
t, err := json.Marshal(&useall)
}
```
`json.Marshal()` 함수는 Go 데이터(주로 구조체 포인터)를 인자로 받아, JSON으로 인코딩된 `[]byte`와 `error`를 반환합니다.
```go
if err != nil {
fmt.Println(err)
} else {
// t는 []byte 타입이므로, 출력을 위해 문자열로 변환합니다.
fmt.Printf("Value %s\n", t)
}
// Unmarshaling할 JSON 문자열 데이터
str := `{"username": "M.", "surname": "Ts", "created":2020}`
```
JSON 데이터는 보통 문자열 형태로 다루어집니다.
```go
// json.Unmarshal 함수는 바이트 슬라이스를 인자로 받으므로, 문자열을 변환합니다.
jsonRecord := []byte(str)
```
`json.Unmarshal()` 함수는 바이트 슬라이스 (`[]byte`)를 인자로 받기 때문에, 먼저 JSON 문자열을 `[]byte` 타입으로 변환해야 합니다.
```go
// 변환된 JSON 데이터를 담을 구조체 변수를 선언합니다.
var temp UseAll
// JSON 바이트 슬라이스를 Go 구조체로 Unmarshaling합니다.
err = json.Unmarshal(jsonRecord, &temp)
```
`json.Unmarshal()` 함수는 JSON 데이터가 담긴 바이트 슬라이스와, 데이터를 채워 넣을 Go 구조체 변수의 **포인터**를 인자로 받습니다. 포인터를 사용하는 이유는 함수가 `temp` 변수의 값을 직접 수정해야 하기 때문입니다. 함수가 종료된 후에도 변경된 값이 유지되려면 이처럼 변수의 메모리 주소를 전달해야 합니다.
```go
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Data type: %T with value %v\n", temp, temp)
}
```
`encodeDecode.go`를 실행하면 다음과 같은 결과가 출력됩니다.
```bash
# go run encodeDecode.go
Value {"username":"Mike","surname":"Tsoukalos","created":2021}
Data type: main.UseAll with value {M. Ts 2020}
```
---
### 전체 예제 코드
```go
package main
import (
"encoding/json"
"fmt"
)
type UseAll struct {
Name string `json:"username"`
Surname string `json:"surname"`
Year int `json:"created"`
}
func main() {
useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}
// Marshaling: Go 구조체 -> JSON
t, err := json.Marshal(&useall)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Value %s\n", t)
}
// Unmarshaling할 JSON 문자열
str := `{"username": "M.", "surname": "Ts", "created":2020}`
jsonRecord := []byte(str)
// 결과를 저장할 구조체 변수
var temp UseAll
// Unmarshaling: JSON -> Go 구조체
err = json.Unmarshal(jsonRecord, &temp)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Data type: %T with value %v\n", temp, temp)
}
}
```
+129
View File
@@ -0,0 +1,129 @@
# Working with JSON
Lets learn how to work with JSON data.
The Go standard library includes `encoding/json`, which is for working with JSON data. Additionally, Go allows us to add support for JSON fields in Go structures using tags. Tags control the encoding and decoding of JSON records to and from Go structures. But first, we should talk about marshaling and unmarshaling JSON records.
## Using `Marshal()` and `Unmarshal()`
Both the marshaling and unmarshaling of JSON data are important procedures for working with JSON data using Go structures. **Marshaling** is the process of converting a Go structure into a JSON record. We usually want that for transferring JSON data via computer networks or for saving it on disk. **Unmarshaling** is the process of converting a JSON record given as a byte slice into a Go structure. We usually want that when receiving JSON data via computer networks or when loading JSON data from disk files.
> **Note:** The number one bug when converting JSON records into Go structures and vice versa is not making the required fields of our Go structures exported. When we have issues with marshaling and unmarshaling, begin our debugging process from there.
# Coding example
The code in `encodeDecode.go` illustrates both the marshaling and unmarshaling of JSON records using hardcoded data for simplicity:
```go
package main
import (
"encoding/json"
"fmt"
)
type UseAll struct {
Name string `json:"username"`
Surname string `json:"surname"`
Year int `json:"created"`
}
```
What the previous metadata tells us is that the `Name` field of the `UseAll` structure is translated to `username` in the JSON record, and vice versa; the `Surname` field is translated to `surname`, and vice versa; and the `Year` structure field is translated to `created` in the JSON record, and vice versa. This information has to do with the marshaling and unmarshaling of JSON data. Other than this, we treat and use `UseAll` as a regular Go structure.
```go
func main() {
useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}
// Regular Structure
// Encoding JSON data -> Convert Go Structure to JSON record with fields
t, err := json.Marshal(&useall)
}
```
The `json.Marshal()` function requires a pointer to a structure variable—its real data type is an empty interface variable—and returns a byte slice with the encoded information and an `error` variable.
```go
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Value %s\n", t)
}
// Decoding JSON data given as a string
str := `{"username": "M.", "surname": "Ts", "created":2020}`
```
JSON data usually comes as a string.
```go
// Convert string into a byte slice
jsonRecord := []byte(str)
```
However, as `json.Unmarshal()` requires a byte slice, we need to convert that string into a byte slice before passing it to `json.Unmarshal()`.
```go
// Create a structure variable to store the result
temp := UseAll{}
err = json.Unmarshal(jsonRecord, &temp)
```
The `json.Unmarshal()` function requires the byte slice with the JSON record and a pointer to the Go structure variable that is going to store the JSON record and returns an `error` variable.
```go
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Data type: %T with value %v\n", temp, temp)
}
```
Running `encodeDecode.go` produces the next output:
```bash
# go run encodeDecode.go
Value {"username":"Mike","surname":"Tsoukalos","created":2021}
Data type: main.UseAll with value {M. Ts 2020}
```
```go
package main
import (
"encoding/json"
"fmt"
)
type UseAll struct {
Name string `json:"username"`
Surname string `json:"surname"`
Year int `json:"created"`
}
func main() {
useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}
// Regular Structure
// Encoding JSON data -> Convert Go Structure to JSON record with fields
t, err := json.Marshal(&useall)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Value %s\n", t)
}
// Decoding JSON data given as a string
str := `{"username": "M.", "surname": "Ts", "created":2020}`
// Convert string into a byte slice
jsonRecord := []byte(str)
// Create a structure variable to store the result
temp := UseAll{}
err = json.Unmarshal(jsonRecord, &temp)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Data type: %T with value %v\n", temp, temp)
}
}
```