저는 최근에 일부 감사 프로세스를 작성했습니다. 이것의 대부분은 임의의 구성을 따로 따로 리플렉션하는 것입니다. 객체 평등을 위해 사용할 수있는 인터페이스가 있습니다. 분리 된 모든 것들이이 인터페이스를 구현하는 것은 아니며 비교는 임의의 유형 (객체 평등은 유형의 평등을 의미하지는 않음) 사이에있을 수 있습니다.어떻게 구현하는지 알고있는 인터페이스에 reflect.Value 구조체를 다시 입력 할 수 있습니까?
비교 대상은 동일한 유형 일 필요가 없기 때문에 무언가가 한쪽면에 포인터이고 다른 쪽 (* 문자열 대 문자열 또는 * ChickenBox 대 BoxOfChicken)의 값이있는 경우가 있습니다. 나는 단순히 포인터/인터페이스 값을 참조 해제했을 때 비교했을 때 비교가 간단합니다.
내 문제는 포인터/인터페이스를 dereferenced 일단 부모 포인터/인터페이스를 구현하는 인터페이스에 어설 션을 입력 할 수없는 것 같습니다. 이 방법을 보여줍니다 : 여기
는 예 ( https://play.golang.org/p/O_dvyW07fu 놀이터) : 인이의package main
import (
"fmt"
"reflect"
)
// ID interface
type IHasID interface {
GetID() string
SetID(id string)
}
// implementing type
type HasID struct {
ID string `bson:"_id,omitempty"`
}
func (be *HasID) GetID() string {
return be.ID
}
func (be *HasID) SetID(id string) {
be.ID = id
}
// static comparison reflect.Type of IHasID
var idType = reflect.TypeOf((*IHasID)(nil)).Elem()
func main() {
testy := struct {
HasID
Somefield int
}{
HasID{
ID: "testymctest",
},
4,
}
id, _ := GetIDFrom(reflect.ValueOf(testy))
fmt.Printf("ID: %v\n", id)
}
// check if the reflect.Value implements IHasID
func ImplementsID(x reflect.Value) bool {
switch x.Kind() {
case reflect.Interface, reflect.Ptr:
if x.IsValid() && !x.IsNil() {
return ImplementsID(x.Elem())
}
case reflect.Struct:
if x.IsValid() {
return reflect.PtrTo(x.Type()).Implements(idType)
}
}
return false
}
// check and get the reflect.Value's ID
func GetIDFrom(x reflect.Value) (string, bool) {
switch x.Kind() {
case reflect.Ptr, reflect.Interface:
if x.IsValid() && !x.IsNil() {
return GetIDFrom(x.Elem())
}
case reflect.Struct:
if x.IsValid() && ImplementsID(x) {
// not using val,ok syntax to demo issue, if it gets here it should
// implement ID since we did the check in the if statement above
val := x.Interface().(IHasID)
return val.GetID(), true
}
}
return "", false
}
나의 이해는 인터페이스가 두 부분 (https://blog.golang.org/laws-of-reflection) 것입니다. 반영 내에서 이것은 반영에 의해 대표된다. 유형 (광범위하게 방법)과 반영. 가치 (광범위하게 데이터). 라인 (53)에 우리가 reflect.PtrTo 사용하여 인터페이스에 대한 우리의 관계를 재구성 할 수 있기 때문에
if x.IsValid() && ImplementsID(x) {
이것은 : 데모 내에서 우리는 통과 reflect.Value의 reflect.Type 라인 67의 인터페이스를 구현하는 성공적으로 평가
return reflect.PtrTo(x.Type()).Implements(idType)
reflect.TYP에서 복제 할 수없는 것은이 프로세스 (reflect.Type 쪽)입니다. 그래서 라인 (70)에 우리는 단순히 (방법이없는) 기본 구조체가이 실패
val := x.Interface().(IHasID)
를 내가 나를 어떻게 할 수있는 구문을 찾을 수 없었습니다 것은 reflect.Type에 불가능했을 것 같다 측면; assert의 인터페이스를 충족하는 구조체에 대해 정의 된 메소드로 돌아온다. (나는 reflect.Type이 캐시 된 인터페이스 스토어에 대해 간단히 작동하고 structs 메소드가이 시점까지 나에게 손실되었다고 생각한다.)
나는 어떤 작업을하기 전에 단순히 포인터/인터페이스의 존재를 강요하는 실무 솔루션을 가지고 있지만 뭔가를 놓친 것처럼 느껴진다. 그 반사를 감안할 때. 값의 반영. 타입이 인터페이스를 성공적으로 찾을 수 있습니다. 내가 반영 할 수있는 비슷한 것이 확실합니다. 가치면?
그리고 내가 반영한 것처럼 그 값을 주소 지정 할 수있는 방법이 없습니다. 유형 측면입니까? – lmunro
@Imunro, 아니요,하지만 포인터로 초기 값을 전달하면됩니다. – OneOfOne
@lmunro : 주소를 지정할 수없는 값의 주소를 취할 방법이 없습니다. 'reflect.New'를 사용하여 구조체에 새로운 포인터를 만들고 이전 값을 복사 할 수는 있지만 처음부터 포인터로 시작하는 것이 더 쉽습니다. – JimB