인터페이스
인터페이스는 메소드의 집합이다. 단 인터페이스에서 메소드를 정의하지는 않는다.
인터페이스를 선언하는 방법은 변수와 선언하는 방법과 같다.
package main import "fmt" type hello interface { // 참고로 인터페이스 명은 주로 -er이 붙는다. } func main() { var first hello fmt.Println(first) // hello 인터페이스는 빈 인터페이스이기에 nil 을 반환 }
GOLANG 에선 빈 인터페이스를 볼 수 있는데 interface {} 으로 표시한다.
이 선언은 Go에서 모든 Type 을 나타내기 위해 사용한다. 흔히 말하는 Dynamic Type 이라 볼 수 있다.
func Marshal(v interface{}) ([]byte, error); func Println(a ...interface{}) (n int, err error);
하나의 구조체로 여러 메소드 또는 여러 인터페이스의 선언도 가능하다.
package main import "fmt" type Sharpe interface { // Area 메소드를 가진 인터페이스 선언 Area() int // Area 메소드에 대한 반환값의 형 int 로 선언 } type Object interface { Volume() int } type Cube struct { // 구조체 Cube side int } func (c Cube) Area() int { // Cube 구조체를 가진 Area 메소드 return 6 * (c.side * c.side) } func (c Cube) Volume() int { // Cube 구조체를 가진 Volume 메소드 return c.side * c.side * c.side } func main() { c := Cube{3} var s Sharpe = c var o Object = c fmt.Println("Sharpe interface :", s.Area()) fmt.Println("Object interface :", o.Volume()) }
┌──(daleji㉿DESKTOP)-[~] └─$ go run interface.go Sharpe interface : 54 Object interface : 27
인터페이스 안에 서로 다른 두 개의 자료형이 있다면 인터페이스에 담긴 실제 타입의 메소드가 호출된다.
package main import "fmt" type MyInt int func (i MyInt) Print() { fmt.Println(i) } type Rectangle struct { width, height int } func (r Rectangle) Print() { fmt.Println(r.width, r.height) } type Printer interface { Print() } func main() { var i MyInt = 5 r := Rectangle{10, 20} var p Printer p = i p.Print() // p를 통하여 MyInt의 Print를 호출한다. p = r p.Print() // p를 통하여 Rectangle의 Print를 호출한다. }
┌──(daleji㉿DESKTOP)-[~] └─$ go run int.go 5 10 20
또한 인터페이스를 호출하는 인터페이스를 만들 수 있다.
package main import "fmt" type All interface { // All 인터페이스를 호출하면 Sharpe 와 Object 도 호출한다. Sharpe Object } type Skin interface { Color() int } type Sharpe interface { Area() int } type Object interface { Volume() int } type Cube struct { side int } func (c Cube) Area() int { return 6 * (c.side * c.side) } func (c Cube) Volume() int { return c.side * c.side * c.side } func main() { c := Cube{3} var a All = c fmt.Println("All interface - Area :", a.Area()) fmt.Println("All interface - Volume :", a.Volume()) // 아래 부분은 타입단언 이라고 부르는 인터페이스명.(타입) 형태로 선언한다. // 해당 문법을 사용해 인터페이스를 구현 했는지, 구현되어 있다면 값을 확인할 수 있다. value1, ok1 := a.(Skin) fmt.Println(value1, ok1) value2, ok2 := a.(All) fmt.Println(value2, ok2) }
┌──(daleji㉿DESKTOP)-[~] └─$ go run interface.go All interface - Area : 54 All interface - Volume : 27 <nil> false {3} true
추가로 찾다보니 타입 변환이라는게 있더라.
타입 변환은 타입 단언 문법과 비슷하지만 switch 문에서만 쓸 수 있다.
package main import ( "fmt" "strings" ) func explain(i interface{}) { switch i.(type) { // 자동으로 타입이 지정됨 case string: fmt.Println("i stored string ", strings.ToUpper(i.(string))) case int: fmt.Println("i stored int", i) default: fmt.Println("i stored something else", i) } } func main() { explain("Hello World") explain(52) explain(true) }