ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [golang] 인터페이스(Interface)
    개발언어/Go 2020. 9. 24. 23:47

     Go의 Interface는 흔히 알고있는 Java의 Interface 개념과는 많이 다르다. 보통 Java에서 Interface라고 하면 반드시 구현이 필요한 메서드 정도로 이해되는데, Go의 Interface는 메서드들의 집합체라고 정의될 수 있다. 아마 이렇게 글만 읽어서는 무슨말인지 모를테니... 간단하게 코드를 보면서 이해해보자.

     

    package main
    
    import "fmt"
    
    // 1. 인터페이스를 정의한다.
    type Figure interface {
        // interface에서 공통으로 묶을 메서드를 정의한다.
    	Area() float32
    }
    
    // 2. 구조체를 정의한다.
    type Square struct {
    	Width  float32
    	Height float32
    }
    
    type Triangle struct {
    	Width  float32
    	Height float32
    }
    
    // 3. 구조체에서 사용할 메서드들을 정의한다.
    func (s Square) Area() float32 {
    	return s.Width * s.Height
    }
    
    func (t Triangle) Area() float32 {
    	return t.Width * t.Height / 2
    }
    
    func main() {
    	// 인터페이스 변수 정의
    	var s, t Figure
        
        // 인터페이스에 구조체를 담는다(?)
    	s = Square{2, 5}
    	t = Triangle{2, 5}
    	fmt.Println(s.Area())
    	fmt.Println(t.Area())
    }
    

     

     

    위의 코드를 보면 알 수 있듯이, 인터페이스 내부에는 함수를 넣을 수 있고, 위의 예제에서는 Figure라는 인터페이스가 Area()라는 함수를 호출할 권리(?)를 가지고 있다. 그리고 아래에 만든 Square와 Triangle은 각각 Area()라는 함수를 갖게 된다.

     

     여기서 중요한 점이 하나 있다. 바로, 완전한 상속은 아니지만, 상속의 개념과 비슷한 방식이 등장한다. 즉, Interface가 가진 메서드를 갖고있는 구조체들은 Interface의 구성원이 될 수 있다는 것이다. 즉, 위의 예제에서는 Square와 Triangle이 Area()라는 메서드를 가지고 있기 때문에 Figure의 구성원이 될 수 있다는 것이다.

     

     이게 어떻게 가능한 것일까? 바로, 'Interfaces are implemented implicitly(인터페이스는 암시적으로 충족가능하다)' 때문에 가능하다. 이걸 쉽게 이야기하자면, 구조체가 인터페이스에 관련되어있다고 명시하지 않더라도 연관된 메서드가 있으면 알아서 찾는다는 것이다.

     

     하나의 예제를 더 들여다보자.

    package main
    
    import "fmt"
    
    type Pet struct {
    	Name string
    	Age  int
    }
    
    func (p Pet) getName() {
    	fmt.Printf("pet name is %s.\n", p.Name)
    }
    
    func (p Pet) getAge() {
    	fmt.Printf("pet age is %d.\n", p.Age)
    }
    
    type GetName interface {
    	getName()
    }
    
    type GetAge interface {
    	getAge()
    }
    
    type PetInfo interface {
    	GetName
    	GetAge
    }
    
    func main() {
    	var i PetInfo
    	i = Pet{"pikachu", 32}
    	i.getAge()
    	i.getName()
    }
    

     

     위의 코드는 첫번째 예제와는 다르다. PetInfo를 보면 알 수 있듯이 인터페이스가 인터페이스를 가지고 있다. 그리고 main에서 PetInfo 변수가 GetAge 인터페이스의 getAge()를 호출하고, GetName 인터페이스가 getName()을 호출하는 것을 보면 알 수 있듯이, 인터페이스가 인터페이스를 호출하면, 호출된 인터페이스의 메서드를 사용할 수 있게된다. 사실상 상속이라고 봐도 무방할 것 같다.

     

     오늘 여기서 기억해야할 점은,

    1. struct가 interface로 정의되려면, struct는 interface가 가지고 있는 메서드를 반드시 가지고 있어야한다는 점.

    2. interface가 interface를 갖는 경우, 상위 인터페이스가 하위 인터페이스의 메서드를 사용할 수 있다는 점.

     

    이 두 가지는 꼭 기억해두자.

    '개발언어 > Go' 카테고리의 다른 글

    [Golang] 마이크로서비스 공통패턴  (0) 2020.10.14
    [Golang] RPC API  (0) 2020.10.12
    [Golang] go에서 RPC 다루기  (0) 2020.10.11
    [Golang] net/http 패키지  (0) 2020.09.30
    [golang] 마샬링(Marshaling)  (0) 2020.09.26
Designed by Tistory.