reflect package 사용하기
TRANSCRIPT
리터럴 관리 기준
Type
Value
“harry potter”
33 int33
Type
Value
stringharry potter
프로그램 언어들에는 리터럴 즉 값을 데이터 타입별로 관리한다.
변수 정의
Type
Value
var s string s = “harry potter”
var x int x = 33 int
x
Type
Value
string
harry potter
변수
33
변수는 데이터 타입을로 정의하고 값을 저장하는 장소를 가진다.
s변수
reflection 이란
var x int x = 33 Type
Value
int
x변수
33
프로그램언어에서 reflection은 변수가 가진 데이터 타입을 인식하여 타입 캐스팅 등의 요건을 처리하는 구조
변수 x 의 타입을 처리reflect.TypeOf(x) reflect.ValueOf(x) 변수 x 의 Value값에 대한 타입을 처리
reflect.ValueOf(x).Int() 변수 x 의 Value에 대한 실제 값을처리
interface{}란
var all_type interface{} var xi int var xs string var xf float32
go lang에서 다른 데이터타입을 받아서 처리할 수 있는 데이터구조
all_type = xi fmt.Println(" int ", reflect.TypeOf(all_type)) all_type = xs fmt.Println(" string ", reflect.TypeOf(all_type)) all_type = xf fmt.Println(" float32 ", reflect.TypeOf(all_type))
예제: interface정의 및 구현(1/3)
type Stringer interface { String() string }
string을 처리하는 하나의 인터페이스 정의하고 타입을 정의하고 인터페이스를 구현함
type Binary uint64
// Binary는 Stringer 인터페이스를 구현한다. func (i Binary) String() string { return strconv.Itoa(i.Get()) }
//int 타입으로 변화 func (i Binary) Get() int { return int(i) }
예제: interface정의 및 구현(2/3)
func ToString(any interface{}) string {
switch vi := any.(type) { case uint64: return strconv.Itoa(int(vi)) case Binary: return strconv.Itoa(int(vi)) }
return "error" }
interface{}로 전달받아 처리하는 ToString함수를 정의
예제: interface정의 및 구현(3/3)
ffunc main() {
b := Binary(200) s := Stringer(b)
var c interface{} = b // 여기서 b 복사본을 만든다.
fmt.Println("string ", s.String()) fmt.Println(" bbbb", b) fmt.Println("ccccc ", c) fmt.Println("bbbbb string ", b.String()) fmt.Println("To String ", ToString(c)) fmt.Println(" String ", s.String())
}
실제 실행해조면 동일 한 값을 출력한다
itable: 인터페이스 테이블b 에 값을 넣고 b를 s에 인터페이스를 넣는다. 인테페이스 구조는 인터페이스 내의 데이터 타입과 실질적인 데이터 값을 저장하는 구조로 관리된다. 정의 메소드등이 있으면 인터페이스 itable에 메소드도 관리한다.
itable 컴퓨팅
가능한 모든 itable을 전부 미리 구성하는 것이 아닙니다. 구조를 만들면 실제 런타임에 실행하면서 처리합니다.
컴파일러는 각 타입에 대한 타입 구조 생성
컴파일러는 각 타입에 대한 메소드 구조 생성
런타임시 itable을 검색하여 메소드를 실행
빈 인터페이스 메모리구조
메모리 최적화: 두가지 케이스 조합
인터페이스 메모리 구조
리플렉션 법칙 (The Laws of Reflection)
Rob Pike의 리플렉션 법칙들
http://blog.golang/laws-of-reflection
reflect.TypeOf(interface {}) Type, reflect.ValueOf(interface{}) Value
1. 리플렉션은 인터페이스 값에서 리플렉션 오브젝트로 됩니다.
2. 리플렉션은 리플렉션 오브젝트에서 인터페이스 값으로 됩니다.
3. 리플렉션 오브텍드를 수정하려면 값은 설정할 수 있어야 됩니다.
canSet( ) bool => true 일 경우만 갱신
1. 리플렉션은 인터페이스 값에서 리플렉션 오브젝트로 됩니다.
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println(“type:”, v.Type())
fmt.Println(“kind is float64:”, v.Kind() == reflect.Float64)
fmt.Println(“value:”, v.Float())
//결과
type: float64
kind is float64: true
value: 3.4
유형(Type) 과 유형(Kind)
var x unit8 = ‘x’
v := reflect.ValueOf(x)
fmt.Println(“type:”, v.Type()) // unit8.
fmt.Print(“kind is unit8: ”,v.Kind() == reflect.Unit8) // true.
x = unit8(v.Unit()) // v.Unit returns a unit64.
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
fmt.Println(“kind is Int: ”, v.Kind() == reflect.Int) // true
2. 리플렉션은 리플렉션 객체에서 인터페이스 값으로 됩니다.
// Interface는 interface{} 처럼 v 값을 반환한다.
// func (v value) Interface() interface{}
y := v.Interface().(float64) // y는 float64 타입을 가질 것이다.
fmt.Println(y)
fmt.Printf(“value is %7.1e\n”, v.Interface()) // 3.4e+00
즉, 인터페이스 메소드는 ValueOf 함수의반대입니다. 그결과는 정적 타입 interface{} 입니다.
반복 : 리플렉션은 인터페이스 값에서 리플렉션 오브젝트로 되고 다시 반대로 됩니다.
3. 리플렉션 오브젝트를 수정하려면 값은 설정 가능할 수 있어야 합니다.
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // 에러: 패닉이 올 것 입니다.
// 패닉 : reflect.Value.SetFloat 비주소적인 값을 이용
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println(“settability of v:”, v.CanSet())
// settability of v: false
“settability”는 무엇인가?
settability는 리플렉션 객체가 원래 항목을 가지고 있는 것에 따라 결정됩니다.
var x float64 = 3.4
// 우리는 여기에서 x이 복사본을 넘겨주고 있습니다.
v := reflect.ValueOf(x)
// f(x) 와 f(&x)의 다른점에 대하여 생각합니다.
// v.SetFloat(7.1) 내부의 리플렉션 값 복사된 값으로 변경됩니다.
그럼, 어떻게 리플렉션 값을 수정할 수 있을까요?
“포인터를 사용합니다, Luke”
var x float64 = 3.4
p := reflect.ValueOf(&x) // x 주소를 가져온다.
fmt.Println("type of p:", p.Type()) // type of p: *float64
fmt.Println("settability of p:", p.CanSet()) // settable of p: false
v := p.Elem()
fmt.Println(" vvvv ", v)
fmt.Println("settable of v:", v.CanSet())
v.SetFloat(7.1)
fmt.Println(v.Interface()) // 7.1
fmt.Println(x) //7.1