Interface

chris·2023년 1월 24일
0

golang

목록 보기
5/8
post-thumbnail

Go 언어에서 interface 타입을 정의할 때 구체적인 동작을 구현할 메소드의 집합을 나열하는 방식으로 표현한다. 어떤 타입이 특정한 interface를 따르기 위해서는, 그 interface에서 정의한 모든 method를 구현해야 한다. 간단히 말해 interface란 abstrct type으로, 정의할 타입이 어떤 interface의 인스턴스가 되기 위해 반드시 구현해야 할 함수들을 정의한 것이다. 이렇게 모든 method를 구현했다면 그 타입은 해당 interface를 satisfy한다고 표현한다.
interface의 가장 큰 장점은, 함수의 매개변수 타입을 interface로 정의했을 때 그 interface를 구현한 변수라면 어떤 것도 그 함수에 전달할 수 있다는 점이다. interface는 특별한 기능을 직접 제공하지 않고 단지 형식을 맞추는 역할만 한다.

interface 구현

type Shape interface {
    area() float64
    perimeter() float64
}
type Rect struct {
    width  float64 
    height float64
}

func (r Rect) area() float64 { 
	return r.width * r.height 
}
func (r Rect) perimeter() float64 {
     return 2 * (r.width + r.height)
}
type Circle struct {
    radius float64
}

func (c Circle) area() float64 { 
    return math.Pi * c.radius * c.radius
}
func showArea(shape Shape) {
	fmt.Println(shape.area())
}

r := Rect{10., 20.}
c := Circle{10}

showArea(r)

// 반면 다음과 같이 사용은 할 수 없다.
// 이유는 Circle은 perimeter()를 구현하지 않았기 때문에 Shape의 instance가 될 수 없다.
showArea(c)

interface 타입

Go 프로그래밍을 하다보면 흔히 빈 인터페이스(empty interface)를 자주 접하게 되는데, 흔히 interface type이라 부른다.
여러 표준패키지들의 함수 Prototype을 살펴보면, 아래와 같이 빈 interface가 자주 등장함을 볼 수 있다.
빈 interface는 interface{} 와 같이 표현한다.
Go의 모든 Type은 적어도 0개의 메소드를 구현하고 있으므로 interface{}는 모든 타입을 표현할 수 있다.
즉 다음 코드의 Println은 모든 Type을 매개변수로 받을 수 있다.

type any = interface{}
...
func Println(a ...any) (n int, err error) {
	return Fprintln(os.Stdout, a...)
}

type assertion

Type assersion이란 x.(T) 형식의 표기법으로, x는 인터페이스 타입을, T는 구체적인 타입을 지정한다. 이 때 x에 실제로 저장되는 값의 타입은 T이며, T는 반드시 x의 인터페이스 타입을 충족해야 한다.
Type assersion으로 할 수 있는 일은 두 가지가 있다.

  1. interface값이 특정한 타입을 따르는 지 확인하는 것이다. Type assersion을 이렇게 활용할 때는 내부값과 bool 타입의 값이라는 두 가지 값을 리턴한다. 내부 값은 실제로 사용하려는 값인 반면, boolean 값은 그 type assersion이 제대로 실행됐는지 여부를 알려준다.
  2. interface에 저장된 구체적인 값을 이용하거나 이 값을 새 변수에 할당하는 것이다.
func main() {
	var myInt interface{} = 123
    
    k, ok := myInt.(int)
    if ok {
    	fmt.Println("Success:", k)
    }
    
    v, ok := myInt.(float64)
    if ok {
    	fmt.Println(v)
    } else {
    	fmt.Println("Failed without panicking!")
    }
}
profile
software engineer

0개의 댓글