프로그래밍/golang

ultimate in go (5)- data structure(embedding)

나도한강뷰 2023. 1. 24. 00:06

임베딩

임베딩이 아닌 필드 선언

type user struct {
    name  string
    email string
}
func (u *user) notify() {
    fmt.Printf("Sending user email To %s<%s>\n", u.name, u.email)
}
type admin struct {
    person user // 임베딩이 아니다.
    level  string
}
func main() {
    ad := admin{
        person: user{
            name:  "Hoanh An",
            email: "hoanhan101@gmail.com",
        },
        level: "superuser",
    }
}
ad.person.notify()
  • admin의 user는 임베딩이 아닌, 하나의 필드를 user라는 타입으로 정의한것
  • admin을 리터럴로 선언한 이후 내부 user또한 리터럴로 선언해 주어야된다.
  • 이럴경우 method를 쓰는 경우 참조는 ad.person.notify같이 모든 구조에 대한 언급이 필요하다.

임베딩 타입

type user struct {
    name  string
    email string
}
func (u *user) notify() {
    fmt.Printf("Sending user email To %s<%s>\n", u.name, u.email)
}
type admin struct {
    user  // 임베딩 타입
    level string
}
func main() {
    ad := admin{
        user: user{
            name:  "Hoanh An",
            email: "hoanhan101@gmail.com",
        },
        level: "superuser",
    }
    // 내부 타입 메서드를 직접 사용 가능하다.
    ad.user.notify()
    ad.notify()
}
  • 다음과 같이 임베딩 타입을 쓰게되면 inner type이 승격하게 된다.
  • 그말은 user의 내부 필드값을 ad.user.name이라고 쓰지않고 ad.name이라고 선언할 수 있는 것과 같다.
  • 그말은 내부 타입과 관련된 모든 것들을 외부 타입에서도 사용할 수 있도록 승격한다는 것과 같다.
  • 임베딩은 서브타입관계를 생성하지않고 admin은 admin, user는 user로 작동한다.
  • 다만 외부타입이 사용할 수 있도록 내부타입을 노출시킬 뿐이다.

동일한 인터페이스가 구현되어 있는 내 외부 타입

type notifier interface {
    notify()
}
type user struct {
    name  string
    email string
}
func (u *user) notify() {
    fmt.Printf("Sending user email To %s<%s>\n", u.name, u.email)
}
type admin struct {
    user
    level string
}
func (a *admin) notify() {
    fmt.Printf("Sending admin email To %s<%s>\n", a.name, a.email)
}
func main() {
    ad := admin{
        user: user{
            name:  "Hoanh An",
            email: "hoanhan101@gmail.com",
        },
        level: "superuser",
    }
}
sendNotification(&ad)
ad.user.notify()
ad.notify()
  • 외부에서 이미 정의된게 있다면, 내부에서 승격은 이루어지지 않고 덮여쓰여진다.
  • 그럼에도 불구하고 내부타입의 매소드를 쓰고싶다면 직접적으로 ad.user.notify같이 써줘야된다.
  • ad.notify로 쓰면 외부타입의 매소드를 사용하게 된다.

exporting(내보내기)

  • 간단함으로 생략
  • package를 통해서 명칭 선언
  • 대문자 외부 노출
  • 소문자 외부 노출x
  • 하지만 함수나 외부에 노출되는 방식 내부에는 외부 노출되지않는것을 사용하여도 에러x
  • struct선언이나 embedding에도 동일하게 적용
  • 그러나 직접 내외부 노출을 결정하는게 좋음