본문 바로가기
프로그래밍/golang

ultimate in go (8)- interface변환 및 주의사항

by 나도한강뷰 2023. 1. 25.

변환

인터페이스 변환

type Mover interface {
    Move()
}
type Locker interface {
    Lock()
    Unlock()
}
type MoveLocker interface {
    Mover
    Locker
}
type bike struct {}
func (bike) Move() {
    fmt.Println("Moving the bike")
}
func (bike) Lock() {
    fmt.Println("Locking the bike")
}
func (bike) Unlock() {
    fmt.Println("Unlocking the bike")
}
func main() {
    var ml MoveLocker
    var m Mover
    ml = bike{}
    m = ml   //ok
    ml = m   //x
}
  • 각각의 매소드에 인터페이스를 설정한다.
  • bike에 필요한 매소드를 선언한다.
  • ml(movelocker interface)에 bike를 대입한다.(각각의 매소드가 정의되어있기때문에 대입가능)
  • 그 ml(movelocker)을 m(mover)에 할당한다. -> 당연히 매소드가 포함되어있기때문에 변환가능하다.
  • 하지만 역으로 다시하려고하면 m(mover)에는 locker에 대해서 정의내려지고 있지않기때문에 lock method missing으로 에러가 발생한다.
  • 실제로 대입되어있는 값이 매소드를 가지고 있을지라도 타입간에 호환이 맞지않기때문에 불가능하다.

    타입 단언(type asserion)

  • 이런 상황에서는 런타임때 타입단언을 사용하여 명시적으로 변환 시킬 수 있다.
  • m.(bike)라는 식의 interface.(type)을 통해서 인터페이스의 타입을 명시적 표시할 수 있다.
  • 이렇게 되면, ml = m.(bike)와 같이 선언할 수 있다.
  • 타입단언을 사용하면 주의해야되는게, 인터페이스로 추상화하고 디커플링시켰는데, 타입단언을 하게되면 이전상태로 돌아가게 되기때문이다.

인터페이스 오염(interface pollution)

  • 구체적인 타입이 아닌 인터페이스로 선언하는건 왜그런가?
    1. 인터페이스를 사용하기위해서 인터페이스를 사용한다
      • 아니다. 인터페이스 사용에는 비용이 들기때문에, 사용에 득보다 실이 많으면 인터페이스를 사용하면 안된다.
    1. 코드 테스트를 위해서 인터페이스를 사용한다
      • 아니다. 개발자를 우선하여서 개발해야한다.
  • 오염된 코드의 예시이다.
type Server interface {
    Start() error
    Stop() error
    Wait() error
}
type server struct {
    host string
}
func NewServer(host string) Server {
    return &server{host} // 외부에서 사용시 export되지않는 타입을 리턴함- 좋지않은 구조
}
func (s *server) Start() error {
    return nil
}
func (s *server) Stop() error {
    return nil
}
func (s *server) Wait() error {
    return nil
}
func main() {
    srv := NewServer("localhost")
    srv.Start()
    srv.Stop()
    srv.Wait()
}
  • 이런경우, srv는 추상화될 필요가 없던 부분이다.
  • interface가 없더라도 달라질게 없는 코드이다.
  • export되지않는 변수를 사용
  • 변화에 잘 대응되도록 디커플링 되어있지않음.

인터페이스 오염 제거

  • server struct -> Server struct, 그리고 newServer 리턴값을 Server struct

  • 그러면 Server가 외부에서 참조가 가능해지고, Server가 매소드를 호출하는 방식으로 변경되게된다.

  • 인터페이스 사용가이드

    • 유저가 api(?)의 실제 구현 디테일을 작성할때
    • api가 유지보수가 필요한 다양한 구현을 가지고 있을때
    • api가 변할수 있을때 디커플링을 사용한다.
  • 이럴때 사용을 다시한번 고려해본다

    • 테스트만을 위해서
    • 변화로 부터 쉽게 대응불가
    • 인터페이스가 코드를 더 좋게 만들어 주지 않는다.

'프로그래밍 > golang' 카테고리의 다른 글

ultimate in go-(10) data race  (0) 2023.01.29
ultimate in go-(9) 동시성(고루틴)  (0) 2023.01.26
ultimate in go(7)- decoupling  (0) 2023.01.24
ultimate in go (6)- grouping  (0) 2023.01.24
ultimate in go (5)- data structure(embedding)  (0) 2023.01.24