템플릿 시스템은 Go의 Reflect 패키지에 크게 의존합니다. 이 패키지로 작업할 때 인터페이스에서 메서드를 동적으로 호출하는 데 어려움을 겪을 수 있습니다. 이 문제는 데이터 유형이 인터페이스로 저장될 때 명백해집니다{}.
인터페이스에 대한 메서드 호출의 역학을 이해하는 것이 중요합니다. 고려해야 할 네 가지 시나리오는 다음과 같습니다.
리플렉션은 인터페이스의 기본 데이터 값을 결정하는 데 도움이 될 수 있습니다. 이 정보를 사용하면 대체 데이터 유형을 생성하고 값과 포인터 수신 방법을 구별할 수 있습니다.
문제를 해결하려면 값과 포인터 표현을 모두 생성해야 합니다. 데이터 유형:
value := reflect.ValueOf(data) if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() // acquire value referenced by pointer } else { ptr = reflect.New(reflect.TypeOf(i)) // create new pointer temp := ptr.Elem() // create variable to value of pointer temp.Set(value) // set value of variable to our passed in value }
두 데이터 유형을 모두 사용하여 메소드 존재 여부를 확인하는 방법은 다음과 같습니다. 간단함:
var finalMethod reflect.Value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].String() }
이 접근 방식을 수용하면 값 또는 포인터 수신기로 정의되었는지 여부에 관계없이 모든 메서드를 동적으로 효과적으로 호출하는 것이 가능해집니다.
package main import ( "fmt" "reflect" ) type Test struct { Start string } // value receiver func (t Test) Finish() string { return t.Start + "finish" } // pointer receiver func (t *Test) Another() string { return t.Start + "another" } func CallMethod(i interface{}, methodName string) interface{} { var ptr reflect.Value var value reflect.Value var finalMethod reflect.Value value = reflect.ValueOf(i) // if we start with a pointer, we need to get value pointed to // if we start with a value, we need to get a pointer to that value if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() } else { ptr = reflect.New(reflect.TypeOf(i)) temp := ptr.Elem() temp.Set(value) } // check for method on value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].Interface() } // return or panic, method not found of either type return "" } func main() { i := Test{Start: "start"} j := Test{Start: "start2"} fmt.Println(CallMethod(i, "Finish")) fmt.Println(CallMethod(&i, "Finish")) fmt.Println(CallMethod(i, "Another")) fmt.Println(CallMethod(&i, "Another")) fmt.Println(CallMethod(j, "Finish")) fmt.Println(CallMethod(&j, "Finish")) fmt.Println(CallMethod(j, "Another")) fmt.Println(CallMethod(&j, "Another")) }
출력:
startfinish startfinish <nil> startanother startfinish startfinish <nil> startanother
위 내용은 값과 포인터 수신기를 모두 처리하면서 Go의 인터페이스에서 메서드를 동적으로 호출하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!