이 글은 현재 작성중입니다.
인터페이스 (Interface)
Go 언어에서 인터페이스는 다양한 타입이 하나의 공통된 동작을 구현할 수 있게 도와줍니다.
구조체는 타입에 포함될 멤버(필드)를 정의하여 만들었다면, 인터페이스는 타입의 동작(메서드)를 정의합니다.
어떤 타입이라도 인터페이스에서 정의한 메서드를 구현한다면, 그 타입은 해당 인터페이스를 구현한 것으로 간주됩니다.
조금 이해가 안될수도 있지만 예제를 따라가보면 이해가 더 쉬울테니 당황하지 마세요.
정의
Go에서 인터페이스를 정의하는 방법은 다음과 같습니다:
type Speaker interface {
Speak() string
}
Go
복사
위 예제에서 Speaker 인터페이스는 Speak 메서드를 정의하고 있으며, 이 메서드는 string 타입의 값을 반환합니다.
구현
글의 처음에서 인터페이스를 구현하려면, 해당 인터페이스에 정의된 모든 메서드를 구현하는 타입을 만들면 된다고 했습니다.
type Person struct {
Name string
}
func (p Person) Speak() string {
return "Hello, my name is " + p.Name
}
Go
복사
위 예제에서 Person 구조체는 Speaker 인터페이스에서 요구하는 메서드인 Speak() 메서드를 구현했기 때문에 Speaker 인터페이스를 구현한 것으로 간주됩니다.
따라서 Person 구조체는 Speaker 인터페이스를 구현한 것이기 때문에, 아래 예제와 같이 Speaker로 취급하여 사용할 수 있습니다.
func SaySomething(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
p := Person{Name: "John"}
SaySomething(p)
}
Go
복사
이처럼 Speaker 인터페이스의 메서드를 모두 구현하기만 한다면 어떤 타입이던지 SaySomething 함수의 매개변수로 사용할 수 있다는 의미입니다.
활용 예시
이 예제 코드는 Go 언어에서 인터페이스를 어떻게 정의하고 구현할 수 있는지를 보여줍니다. 여기서 Speaker라는 인터페이스를 정의하고, Person과 Dog라는 두 개의 구조체가 이 인터페이스를 구현합니다.
(어떤 것이든 소리낼 수 있는 것들은 모두 Speaker로 취급한다고 생각하면 이해가 편하실 겁니다.)
package main
import "fmt"
// Speaker 인터페이스 정의
type Speaker interface {
Speak() string
}
// Person 구조체 정의
type Person struct {
Name string
}
// Person 구조체의 Speak 메서드 구현
func (p Person) Speak() string {
return "Hello, my name is " + p.Name
}
// Dog 구조체 정의
type Dog struct {
Name string
}
// Dog 구조체의 Speak 메서드 구현
func (d Dog) Speak() string {
return "Woof! I am " + d.Name
}
// SaySomething 함수 정의
func SaySomething(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
p := Person{Name: "John"}
d := Dog{Name: "Buddy"}
SaySomething(p)
SaySomething(d)
}
// 실행 결과
// Hello, my name is John
// Woof! I am Buddy
Go
복사
비어있는 인터페이스 (Empty Interface)
Go 언어에서 비어있는 인터페이스 interface{} 는 어떤 타입이든 저장할 수 있는 특수한 인터페이스입니다. 즉, Go의 모든 타입은 비어있는 인터페이스를 구현한 것으로 간주됩니다.
정의
비어있는 인터페이스는 다음과 같이 정의됩니다.
var x interface{}
Go
복사
위의 예제에서 x는 비어있는 인터페이스 타입입니다. 따라서 x에는 어떤 값이든 할당할 수 있습니다.
활용 방법
비어있는 인터페이스는 다양한 상황에서 유용하게 사용될 수 있습니다. 특히, 함수의 매개변수나 반환값으로 활용하여 다양한 타입의 값을 처리할 수 있게 해줍니다.
값 저장
비어있는 인터페이스는 어떤 타입의 값이든 저장할 수 있습니다.
var x interface{}
x = 42
fmt.Println(x) // 출력: 42
x = "Hello, World"
fmt.Println(x) // 출력: Hello, World
x = true
fmt.Println(x) // 출력: true
Go
복사
함수 매개변수로 사용
비어있는 인터페이스를 함수의 매개변수로 사용하면, 함수가 어떤 타입의 값이든 받을 수 있게 됩니다.
func PrintValue(v interface{}) {
fmt.Println(v)
}
func main() {
PrintValue(42)
PrintValue("Hello, World")
PrintValue(true)
}
Go
복사
타입 단언 (Type Assertion)
비어있는 인터페이스에 저장된 값을 원래의 타입으로 사용하려면, 타입 단언(type assertion)을 사용해야 합니다.
func main() {
var x interface{} = "Hello, World"
// 타입 단언을 통해 x를 string 타입으로 변환
s, ok := x.(string)
if ok {
fmt.Println(s) // 출력: Hello, World
} else {
fmt.Println("타입 단언 실패")
}
}
Go
복사
타입 스위치 (Type Switch)
비어있는 인터페이스에 저장된 값의 타입을 판별하는 방법으로 타입 스위치(type switch)를 사용할 수 있습니다.
func PrintType(x interface{}) {
switch v := x.(type) {
case int:
fmt.Printf("정수: %d\n", v)
case string:
fmt.Printf("문자열: %s\n", v)
case bool:
fmt.Printf("불리언: %t\n", v)
default:
fmt.Printf("알 수 없는 타입: %T\n", v)
}
}
func main() {
PrintType(42)
PrintType("Hello, World")
PrintType(true)
}
Go
복사
강의 목록