리플렉션 기초
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 83번째.
Reflection을 사용하면 프로그램이 런타임에 자신의 구조를 검사하고 조작할 수 있습니다. Go의 reflect 패키지는 이러한 기능을 제공하여 타입을 검사하고, 구조체 필드를 읽으며, 메서드를 동적으로 호출할 수 있게 합니다.
리플렉션의 두 가지 핵심 타입은 reflect.Type과 reflect.Value입니다. reflect.TypeOf()와 reflect.ValueOf()를 사용하여 이를 얻습니다:
import "reflect"
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
fmt.Println(t.Name()) // Person
fmt.Println(t.Kind()) // struct
fmt.Println(v.NumField()) // 2구조체 필드를 반복하여 이름, 유형 및 값을 검사할 수 있습니다.
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
// 출력:
// Name: Alice
// Age: 30Reflection은 강력하지만 다음과 같은 상충 요소가 있습니다. 컴파일 시간 형식 검사를 우회하고, 직접 액세스보다 느리게 실행되며, 코드를 이해하기 어렵게 만듭니다. JSON 마샬링, ORM 매핑 또는 컴파일 시간에 형식을 알 수 없는 범용 유틸리티 구축과 같은 작업에만 신중하게 사용하세요.
챌린지
쉬움리플렉션을 사용해 모든 구조체를 검사하고 그 구조를 보고하는 구조체 검사기를 만들어 봅시다! 이는 리플렉션의 실용적인 활용 사례로, 컴파일 시점에 알 수 없는 타입과 함께 작동하는 유틸리티를 만드는 방법입니다.
코드를 두 개의 파일로 나누어 구성합니다:
inspector.go: 리플렉션 기반 검사 유틸리티를 만듭니다.reflect패키지를 사용해 전달된 모든 구조체를 검사하는InspectStruct(v any) string함수를 작성하세요. 함수는 다음 내용을 포함하는 형식화된 보고서를 반환해야 합니다:- 구조체의 타입 이름
- 구조체의 종류 ("struct"여야 함)
- 필드의 개수
- 각 필드에 대해: 필드 이름, 타입, 현재 값
출력 형식은 다음과 같아야 합니다:
Type: [TypeName] Kind: struct Fields: [count] - [FieldName] ([FieldType]): [Value] - [FieldName] ([FieldType]): [Value] ...타입 정보를 가져오려면
reflect.TypeOf()를 사용하고, 필드 값에 접근하려면reflect.ValueOf()를 사용하세요.NumField()를 사용해 필드를 순회하고, 메타데이터에는 타입의Field(i)를, 실제 값에는 값의Field(i)를 사용하세요.main.go: 샘플 구조체를 정의하고 검사기를 사용합니다.구조체 타입(
product또는employee)과 해당 필드 값을 읽은 다음, 적절한 구조체를 생성하고 검사하세요.product의 경우:Name(string),Price(float64),InStock(bool) 필드를 가진Product구조체를 생성하세요. 이름, 가격, 재고 상태를 읽습니다.employee의 경우:ID(int),Name(string),Department(string) 필드를 가진Employee구조체를 생성하세요. ID, 이름, 부서를 읽습니다.생성한 구조체를
InspectStruct에 전달하고 결과를 출력하세요.
다음 입력이 제공됩니다:
- 첫 번째 줄: 구조체 타입 (
product또는employee) - 다음 줄들: 해당 구조체 타입의 필드 값
예를 들어 다음이 주어졌을 때:
product
Laptop
999.99
true출력은 다음과 같아야 합니다:
Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): true그리고 다음이 주어졌을 때:
employee
42
Alice Johnson
Engineering출력은 다음과 같아야 합니다:
Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): Engineering또한 다음이 주어졌을 때:
product
Headphones
79.50
false출력은 다음과 같아야 합니다:
Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): false검사기가 구조를 미리 알지 못해도 서로 다른 구조체 타입과 함께 작동하는 것을 확인하세요. 이것이 바로 리플렉션의 강력함입니다! 동일한 InspectStruct 함수가 Product와 Employee 구조체를 모두 동적으로 처리합니다.
직접 해보기
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Name, Price, InStock 필드를 가진 Product 구조체
type Product struct {
Name string
Price float64
InStock bool
}
// ID, Name, Department 필드를 가진 Employee 구조체
type Employee struct {
ID int
Name string
Department string
}
func main() {
reader := bufio.NewReader(os.Stdin)
// 구조체 타입 읽기
structType, _ := reader.ReadString('\n')
structType = strings.TrimSpace(structType)
if structType == "product" {
// product 필드 읽기
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
inStockStr, _ := reader.ReadString('\n')
inStockStr = strings.TrimSpace(inStockStr)
inStock, _ := strconv.ParseBool(inStockStr)
// TODO: 읽은 값으로 Product 구조체 생성
// TODO: product로 InspectStruct를 호출하고 결과 출력
} else if structType == "employee" {
// employee 필드 읽기
idStr, _ := reader.ReadString('\n')
idStr = strings.TrimSpace(idStr)
id, _ := strconv.Atoi(idStr)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
department, _ := reader.ReadString('\n')
department = strings.TrimSpace(department)
// TODO: 읽은 값으로 Employee 구조체 생성
// TODO: employee로 InspectStruct를 호출하고 결과 출력
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서직접 연습해 보세요: 온라인 Go 컴파일러