Scroll Top

GOLANG – 인터페이스

GO

인터페이스

인터페이스는 메소드의 집합이다. 단 인터페이스에서 메소드를 정의하지는 않는다.

인터페이스를 선언하는 방법은 변수와 선언하는 방법과 같다.

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)
}

Leave a comment

You must be logged in to post a comment.