2014-09-08 2 views
2

내 패키지에 다음과 같은 구조체가 있습니다.부모 내장 구조체 필드 값을 가져 오는 방법은 무엇입니까?

type Animal struct { 
    Id string 
    // and some more common fields 
} 

내 패키지를 사용하는 사용자는 자신의 Animal을 구현할 수 있어야합니다. 내 메소드 중 하나에서 Id이 필요하므로 사용자는 내 구조체를 임베드해야합니다. 내 패키지에서

type Dog struct { 
    Animal 
    Name string 
    Legs int 
} 

나는 데이터베이스에 Animal의를 저장하는 save() 기능을 가지고있다. 사용자의 유형을 모르므로 인수 유형으로 interface{}을 사용해야합니다. 내 질문은 : Id (부모 구조체 Animal)에서 어떻게 얻을 수 있습니까? 지금은 JSON 파싱 및 언 마샬링을 사용하지만이 방법이 있습니까?

func put(doc interface{}) error { 
    res, err := json.Marshal(doc) 
    if err != nil { 
    return err 
    } 
    var animal *Animal 
    err = json.Unmarshal(res, &animal) 
    if err != nil { 
    return err 
    } 
    fmt.Println(animal.Id) // finally I have the Id 
    // ... 
} 

당신이 순서에 인터페이스를 추가 할 수 있습니다 어쩌면

func main() { 
    bello := Dog{ 
    Animal: Animal{ 
     Id: "abcd1234", 
    }, 
    Name: "bello", 
    Legs: 4, 
    } 
    err := put(bello) 
    // ... 
} 

답변

2

사용이 부모 구조체에 대한 참조를 가져해야 할 :

type AnimalGetter interface { 
    GetAnimal() *Animal 
} 

func (dog *Dog) GetAnimal() *Animal { 
    return &dog.Animal 
} 

할 방법을 저장하여 허용 할 그 타입 어설 션 (AnimalGetter) :

func save(obj interface{}) { 
    animal := obj.(AnimalGetter) 
    fmt.Printf("%v\n", animal.GetAnimal()) 
} 

전체 예제보기 : play.golang.org.

출력 :

&{{dogid} wouf 0} 
&{dogid} 

간단한 :

func save(animal AnimalGetter) { 
    fmt.Printf("%v\n", animal.GetAnimal()) 
} 

(play.golang.org) @VonC가 힘을 제안처럼 아마도 인터페이스를 사용하지만

+0

'저장 (AnimalGetter)'하고 캐스팅을 저장하지 않는 이유는 무엇입니까? –

+0

@ Not_a_Golfer 확실하게, 나는 질문 ('put'또는 'save {interface {})'에서 언급 한 것과 같은 서명을 사용하고 있었고 제안에 따라 답변을 편집했습니다. – VonC

+0

사소한 nitpick : getter가 있어야합니다. [Effective Go] (http://golang.org/doc/effective_go)에 따라'GetAnimal() '이 아니라'Animal()'이라고 불린다.html # Getters). –

1

당신은,이 작은 반사 트릭을 할 수 보다 실용적이고 관용적 인 접근 방식이 될 수 있습니다.

어쨌든

가 여기에 반사 달성 동일합니다 :

func main() { 

    d := Dog { 
     Animal { "id1111" }, 
     "Barky", 
     4, 
    } 
    fmt.Println(reflect.ValueOf(d).FieldByName("Animal").Interface().(Animal)) 
} 
+0

나는 처음에는 반사를 피하고, API가 동물을 더 잘 보이게 할 것을 선호했다. 그러나 반성은 확실히 작동 할 수 있습니다. – VonC

2

가는 방법/인터페이스로 Animal를 선언 여기에 이동

type Animal interface { 
    ID() int 
    Name() string 
    // Other Animal field getters here. 
} 

그런 다음, save는로 Animal 걸릴 수 있습니다 인수를하고 Animal의 메소드를 사용하여 필요한 모든 정보를 얻으십시오.

다른 가능성있는 방법은 reflect 패키지를 사용하여 구조체에서 Animal 필드를 얻는 것입니다.하지만이 방법은 인터페이스를 사용하여 더럽고 더러워지며 느려질 수 있습니다.

관련 문제