Go에서 인터페이스는 데이터가 아닌 기능을 정의한다는 사실을 잘 알고 있습니다. 일련의 메소드를 인터페이스에 넣었지만 해당 인터페이스를 구현하는 모든 것에 필요한 필드를 지정할 수 없습니다.
예를 들면 :
// Interface
type Giver interface {
Give() int64
}
// One implementation
type FiveGiver struct {}
func (fg *FiveGiver) Give() int64 {
return 5
}
// Another implementation
type VarGiver struct {
number int64
}
func (vg *VarGiver) Give() int64 {
return vg.number
}
이제 인터페이스와 그 구현을 사용할 수 있습니다.
// A function that uses the interface
func GetSomething(aGiver Giver) {
fmt.Println("The Giver gives: ", aGiver.Give())
}
// Bring it all together
func main() {
fg := &FiveGiver{}
vg := &VarGiver{3}
GetSomething(fg)
GetSomething(vg)
}
/*
Resulting output:
5
3
*/
이제 할 수없는 것은 다음과 같습니다.
type Person interface {
Name string
Age int64
}
type Bob struct implements Person { // Not Go syntax!
...
}
func PrintName(aPerson Person) {
fmt.Println("Person's name is: ", aPerson.Name)
}
func main() {
b := &Bob{"Bob", 23}
PrintName(b)
}
그러나 인터페이스와 임베디드 구조체를 가지고 놀아 본 후, 저는이 작업을 수행하는 방법을 발견했습니다.
type PersonProvider interface {
GetPerson() *Person
}
type Person struct {
Name string
Age int64
}
func (p *Person) GetPerson() *Person {
return p
}
type Bob struct {
FavoriteNumber int64
Person
}
포함 된 구조체 때문에 Bob은 Person이 가진 모든 것을 가지고 있습니다. 또한 PersonProvider 인터페이스를 구현하므로 해당 인터페이스를 사용하도록 설계된 함수에 Bob을 전달할 수 있습니다.
func DoBirthday(pp PersonProvider) {
pers := pp.GetPerson()
pers.Age += 1
}
func SayHi(pp PersonProvider) {
fmt.Printf("Hello, %v!\r", pp.GetPerson().Name)
}
func main() {
b := &Bob{
5,
Person{"Bob", 23},
}
DoBirthday(b)
SayHi(b)
fmt.Printf("You're %v years old now!", b.Age)
}
다음은 위의 코드를 보여주는 Go Playground 입니다.
이 방법을 사용하면 동작이 아닌 데이터를 정의하는 인터페이스를 만들 수 있으며, 해당 데이터를 임베딩하는 것만으로 모든 구조체에서 구현할 수 있습니다. 포함 된 데이터와 명시 적으로 상호 작용하고 외부 구조체의 특성을 인식하지 못하는 함수를 정의 할 수 있습니다. 그리고 모든 것은 컴파일 타임에 확인됩니다! (내가 알 수있는 유일한 방법 은 콘크리트가 아닌에 인터페이스 PersonProvider
를 포함하는 것입니다. 런타임에 컴파일되고 실패합니다.)Bob
Person
자, 여기 내 질문이 있습니다. 이것은 깔끔한 속임수입니까, 아니면 다르게해야합니까?