- 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
- 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.
인터페이스 사용하기
이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07
인터페이스는 메서드 집합입니다. 단 인터페이스는 메서드 자체를 구현하지는 않습니다.
- type 인터페이스명 interface { }
package main
import "fmt"
type hello interface { // 인터페이스 정의
}
func main() {
var h hello // 인터페이스 선언
fmt.Println(h) // <nil>: 빈 인터페이스이므로 nil이 출력됨
}
nil
인터페이스를 선언하는 방법은 변수를 선언하는 방법과 같습니다. 즉, var 변수명 인터페이스
형식으로 선언합니다. 그리고 인터페이스는 다른 자료형과 동일하게 함수의 매개변수, 리턴값, 구조체의 필드로 사용할 수 있습니다.
여기서는 빈 인터페이스를 정의하고 선언해보았습니다. 빈 인터페이스기 때문에 할 수 있는 것이 없으며 fmt.Println으로 출력해봐도 nil이 나옵니다.
이제 메서드를 가지는 인터페이스를 정의해보겠습니다.
- type 인터페이스명 interface { 메서드 }
type 인터페이스명 interface {
메서드1() 리턴값_자료형
메서드2() // 리턴값이 없을 때
}
{ }
(중괄호) 블록안에 메서드 이름, 매개변수 자료형, 리턴값 자료형을 지정하여 한 줄 씩 나열합니다. 여기서는 ,
(콤마)로 구분하지 않습니다.
다음은 int 자료형에 메서드를 연결하고, 인터페이스로 해당 메서드를 호출합니다.
package main
import "fmt"
type MyInt int // int형을 MyInt로 정의
func (i MyInt) Print() { // MyInt에 Print 메서드를 연결
fmt.Println(i)
}
type Printer interface { // Print 메서드를 가지는 인터페이스 정의
Print()
}
func main() {
var i MyInt = 5
var p Printer // 인터페이스 선언
p = i // i를 인터페이스 p에 대입
p.Print() // 5: 인터페이스를 통하여 MyInt의 Print 메서드 호출
}
먼저 type 새_자료형 자료형
형식으로 기존 자료형을 새 자료형으로 정의할 수 있습니다. 여기서는 기본 자료형인 int에 메서드를 연결하기 위해 MyInt를 새로 정의했습니다. 그 다음 MyInt에 Print 메서드를 연결하고, 현재 변수의 값을 출력하도록 구현하였습니다.
이제 인터페이스를 정의합니다. 보통 인터페이스의 이름은 ~er 형태로 짓습니다(예: Reader, Writer). 우리는 Print 함수를 가지는 Printer 인터페이스를 정의했습니다.
type Printer interface {
Print()
}
main 함수 안에서 인터페이스를 선언한 뒤 변수를 대입합니다. 그리고 인터페이스에 .
(점)을 사용하여 메서드를 호출합니다. 여기서는 p.Print()처럼 인터페이스의 Print 메서드를 호출했지만 실제로는 MyInt의 Print 메서드가 호출됩니다. 즉 인터페이스에 담긴 실제 타입(자료형, 구조체)의 메서드가 호출됩니다.
이제 인터페이스를 제대로 활용하기 위해 각기 다른 자료형 두 개를 인터페이스 한 개에 담아보겠습니다. 다음은 int 자료형과 사각형 구조체의 내용을 출력하고, int 자료형과 사각형 구조체의 인스턴스를 담을 수 있는 인터페이스를 정의한 예제입니다.
package main
import "fmt"
type MyInt int // int 형을 MyInt로 정의
func (i MyInt) Print() { // MyInt에 Print 메서드를 연결
fmt.Println(i)
}
type Rectangle struct { // 사각형 구조체 정의
width, height int
}
func (r Rectangle) Print() { // Rectangle에 Print 메서드를 연결
fmt.Println(r.width, r.height)
}
type Printer interface { // Print 메서드를 가지는 인터페이스 정의
Print()
}
func main() {
var i MyInt = 5
r := Rectangle{10, 20}
var p Printer // 인터페이스 선언
p = i // i를 인터페이스 p에 대입
p.Print() // 5: 인터페이스 p를 통하여 MyInt의 Print 메서드 호출
p = r // r을 인터페이스 p에 대입
p.Print() // 10 20: 인터페이스 p를 통하여 Rectangle의 Print 메서드 호출
}
MyInt를 정의하고, 너비와 높이를 가지는 사각형 구조체 Rectangle을 정의했습니다. 그리고 MyInt, Rectangle 모두 자신의 내용을 출력하는 Print 함수를 구현했습니다. 이제 두 타입 모두 똑같은 Print 함수를 가지고 있습니다(여기서 똑같은 함수라는 것은 함수 이름, 매개변수 자료형, 리턴값 자료형이 모두 같은 상태를 뜻합니다).
MyInt 자료형, Ractangle 구조체, Printer 인터페이스를 그림으로 표현하면 다음과 같습니다.
이제 인터페이스를 사용해보겠습니다.
func main() {
var i MyInt = 5
r := Rectangle{10, 20}
var p Printer // 인터페이스 선언
p = i // i를 인터페이스 p에 대입
p.Print() // 5: 인터페이스 p를 통하여 MyInt의 Print 메서드 호출
p = r // r을 인터페이스 p에 대입
p.Print() // 10 20: 인터페이스 p를 통하여 Rectangle의 Print 메서드 호출
}
Printer 인터페이스 p에 MyInt 형 변수 i를 대입했습니다. 마찬가지로 다시 p에 Rectangle 인스턴스를 대입했습니다. 이렇게 전혀 다른 타입을 인터페이스에 대입할 수 있습니다. 즉 인터페이스는 자료형이든 구조체든 타입에 상관없이 메서드 집합만 같으면 동일한 타입으로 봅니다.
인터페이스의 메서드를 호출하면 인터페이스에 담긴 실제 타입의 메서드가 호출되므로 MyInt 형 변수를 대입한 뒤 Print 함수를 호출하면 5가 출력되고, Rectangle 인스턴스를 대입하면 10과 20이 출력됩니다.
인터페이스를 선언하면서 초기화하려면 다음과 같이 :=를 사용하면 됩니다. 인터페이스에는 ( )
(괄호)를 사용하여 변수나 인스턴스를 넣어줍니다.
var i MyInt = 5
r := Rectangle{10, 20}
p1 := Printer(i) // 인터페이스를 선언하면서 i로 초기화
p1.Print() // 5
p2 := Printer(r) // 인터페이스를 선언하면서 r로 초기화
p2.Print() // 10 20
다음과 같이 배열(슬라이스) 형태로도 인터페이스를 초기화 할 수 있습니다.
var i MyInt = 5
r := Rectangle{10, 20}
pArr := []Printer{i, r} // 슬라이스 형태로 인터페이스 초기화
for index, _ := range pArr {
pArr[index].Print() // 슬라이스를 순회하면서 Print 메서드 호출
}
for _, value := range pArr {
value.Print() // 슬라이스를 순회하면서 Print 메서드 호출
}
저작권 안내
이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.- 블로그, 게시판 등에 퍼가는 것을 금지합니다.
- 비공개 포스트에 퍼가는 것을 금지합니다.
- 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
- 링크 및 SNS 공유는 허용합니다.