본문 바로가기
프로그래밍/Go언어

Golang interface에 대한 설명....

by Hwan2 2021. 6. 6.
728x90
반응형

 

 

 

 

 

Go는 기본적으로 상속을 지원하지 않습니다. 단, interface를 제공함으로써 추상화를 돕고, 객체들을 서로 연결시켜주는 역할을 해줍니다.

단, 상속이 아니기 때문에 dependency가 낮으며, 느슨한 관계가 됩니다. 이는 Go언어의 설계목적에 있는것이죠. 

 

1. interface 선언방법

type Calculator interface {...}

 Golang의 guideline을 보면 interface를 선언할 때 시작문자는 대문자로, 단어 끝에는 -er로 끝나도록 만들라고 합니다.

즉, 어떠한 일을 하는 행위자를 표현하는것이 좋습니다.

 

기본적으로 golang의 struct는 상속이 없기때문에, insterface안에 선언된 함수들을 사용하려면 리시버라는 기능을 통해함수를 따로 정의해야 합니다.

 

2. interface 정의방법

package main

import "fmt"

type Calculator interface {
	plus() int
	minus() int
}

//Parameter 정의
type Parameter struct {
	n1, n2 int
}

//Parameter 타입에 대한 Calculator 인터페이스 구현
func (r Parameter) plus() int {
	return r.n1 + r.n2
}

func (r Parameter) minus() int {
	return r.n1 - r.n2
}

func showCalc(calc Calculator) {
	fmt.Println(calc.plus())
	fmt.Println(calc.minus())
}

func main() {
	r := Parameter{30, 20}
	showCalc(r)
}

 

이런식으로 구현하게 됩니다. 리시버 받는 구간은 plus()함수를 정의한 부분이며, 보시면 (r Parameter)부분을 볼 수 있습니다.

저렇게 되면 해당 struct는 인터페이스와 연결된 상태가 되며, showCalc()부분을 보면 인자값을 Calculator로 받는걸 확인할 수 있습니다.

 

해당 리시버는 포인터로도 받는것이 가능합니다.

 

package main

import "fmt"

type Calculator interface {
	plus() int
	minus() int
}

//Parameter 정의
type Parameter struct {
	n1, n2 int
}

//Parameter 타입에 대한 Calculator 인터페이스 구현
func (r *Parameter) plus() int {
	return r.n1 + r.n2
}

func (r *Parameter) minus() int {
	return r.n1 - r.n2
}

func showCalc(calc Calculator) {
	fmt.Println(calc.plus())
	fmt.Println(calc.minus())
}

func main() {
	r := &Parameter{30, 20}
	showCalc(r)
}

포인터로 받으면 리시버로 들어어가는 값은 복사된 Value 값이 아닌 주소값이 들어가면서 복사가 이뤄지지 않습니다.

 

(바뀐 부분은 main() 쪽과 plus(), minus() 부분 리시버 부분이 바뀌었습니다.)

 

3. interface type

인터페이스 타입이 있습니다. 변수에 선언할 수 있으며, C++이나 C의 void* 과 동일한 역할을 수행합니다.

package main

import (
	"fmt"
	"reflect"
)

func typeCheck(x interface{}) {
	fmt.Println(reflect.TypeOf(x))
}

func main() {
	var x interface{}
	x = 1

	fmt.Println(x)	// output : 1
	typeCheck(x)	// output : int

	x = "Tom"
	fmt.Println(x)	// output : Tom
	typeCheck(x)	// output : string
}

 

저런식으로 x에 대해서 선언하게 되면 void* 효과를 가져오기 때문에 x에는 어떤 값이든 들어갈 수 있습니다.

 

 

4. Type Assertion

package main

import "fmt"

func main() {
	var x interface{} = 1

	i := x
	j := x.(int)
	z := x.(string)

	fmt.Println(i) // output : 1
	println(i)     // output : 주소값 출력
	println(j)     // output : 1
	println(z)	// error!! (panic: interface conversion: interface {} is int, not string)
}

 

인스턴스로 변수를 선언 후 값을 입력하면, 해당 값에대한 타입이 정의되어 다음과 같이 출력됩니다.

 

하지만 z 변수의 경우 x는 string에 대한 값이 아니기 때문에 error를 출력하면서 프로그램이 종료됩니다.

 

이를 방지하기 위해 error 값을 return 받으면 되는데, bool 형식으로 return 하게 됩니다.

 

package main

import "fmt"

func main() {
	var x interface{} = 1

	z, flag := x.(string)

	println(z, flag) // false
}

 

z에는 반환된 값이 없기 때문에 아무것도 없지만, type을 찍어보면 x는 string으로 되어 있습니다.

flag에는 bool자료형의 false가 저장되게 됩니다.

 

5. Type Switch

package main

import (
	"fmt"
	"reflect"
)

func typeSwitch(n interface{}) {
	switch n.(type) {
	case string:
		fmt.Println("string")
	case int:
		fmt.Println("int")
	default:
		fmt.Println(reflect.TypeOf(n))
	}
}

func main() {
	var x interface{} = 1

	i := x
	j := x.(int)
	z, flag := x.(string)

	typeSwitch(i)	// output : string
	typeSwitch(j)	// output : int
	typeSwitch(z)	// output : string
	typeSwitch(flag)// output : bool

}

 

저렇게 switch문을 활용하여 type별로 case를 만들어 처리할 수 있습니다.

 

이를 통해 코드를 동적으로 접근이 가능하죠.

 

6. Embedding Interfaces

Go에서 interface는 한번에 여러개를 가져올 수 없지만 여러개의 interface를 하나의 interface로 묶는것이 가능합니다.

 

type ABC interface {
	abc()
}

type ZXC interface {
	zxc()
}

type Marge interface {
	ABC
	ZXC
}

OR

type ABC interface {
	abc()
}

type ZXC interface {
	zxc()
}

type Marge interface {
	abc()
	zxc()
}

 

이런식으로 묶을 수 있습니다.

 

다음은 사용하는 예제를 보도록 하죠.

package main

import "fmt"

type ABC interface {
	abc()
}

type ZXC interface {
	zxc()
}

type Marge interface {
	ABC
	ZXC
}

type Edge struct {
	x int
}

func (e Edge) abc() {
	fmt.Println(e.x + 100)
}

func (e Edge) zxc() {
	fmt.Println(e.x - 100)
}

func main() {
	edge := Edge{10}
	var marge Marge = edge

	marge.abc()	//output : 110
	marge.zxc()	//output : -90
}

 

위처럼 Marge라는 interface로 묶어서 실행이 가능 합니다.

 

 

더 자세한 예제나 코드를 보시려면 아래 링크를 참고해주세요.

 

참고 : 

https://www.geeksforgeeks.org/embedding-interfaces-in-golang/

 

Embedding Interfaces in Golang - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

https://golang.org/doc/effective_go

 

Effective Go - The Go Programming Language

Effective Go Introduction Go is a new language. Although it borrows ideas from existing languages, it has unusual properties that make effective Go programs different in character from programs written in its relatives. A straightforward translation of a C

golang.org

 

 

 

 

 

 

반응형

댓글


스킨편집 -> html 편집에서