본문으로 바로가기

인터페이스는 (1) 구체화된 타입으로 변환할 수도 있고, (2) 다른 인터페이스로 변환할 수도 있습니다.

interface.(type) 꼴로 두 경우 다 방법은 똑같습니다. 

 

인터페이스 변수에서 다른 구체화된 타입으로 변환하기

인터페이스 변수에서는 인터페이스에 해당하는 구조체의 필드에 직접 접근할 수 없습니다.

따라서 인터페이스 변수를 받는 함수는 변수를 구조체로 타입 변환해줄 필요가 있습니다.

아래 코드를 보면 직관적으로 이해할 수 있습니다.

package main

import "fmt"

// String 메서드를 가지면 모두 Stringer 인터페이스 타입
type Stringer interface{
	String() string
}

type Student struct {
	Age int
}

// Student에 String 메서드 추가. 이로써 Stringer 인터페이스 타입이 됨.
func (s *Student) String() string {
	return fmt.Sprintf("Student Age:%d", s.Age)
}

func PrintAge(stringer Stringer) {
	fmt.Println(stringer.String()) // 인터페이스 변수에서 접근가능한 건 정의한 메서드 뿐임
	// struct의 변수에 접근하기 위해 인터페이스 변수를 구체적인 타입으로 변환. 여기선 *Student struct로 변환
	s := stringer.(*Student) 

	fmt.Printf("Age : %d\n", s.Age)
}

func main() {
    s := &Student{Age: 15}
	PrintAge(s)
}

 

위 코드도 작동하지만 좀 더 꼼꼼하게 변환을 하려면, 타입 변환이 성공했는지의 여부를 두번째 반환값으로 받을 수 있습니다.

변환이 성공적이라면 true를, 실패라면 false를 반환합니다. 잘 체크해서 런타임 오류를 발생시키지 않도록 합시다.

func PrintAge(stringer Stringer) {	
	// 타입 변환 결과가 성공적이라면 ok가 true, 실패면 false 반환
	s, ok := stringer.(*Student) 
	if !ok {
		fmt.Println("error")
	}
	fmt.Printf("Age : %d\n", s.Age)
}

 

위 코드도 길다! 하면 아래처럼 한 줄로 작성할 수도 있습니다. 변환 결과가 true면 if문 이하를 실행하고 아니면 else로 빠지는 식으로요.

func PrintAge(stringer Stringer) {	
	if s, ok := stringer.(*Student); ok {
		fmt.Printf("Age : %d\n", s.Age)
	} else {
		fmt.Println("error")
	}
}

 

 

 

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체