본문 바로가기
Go

[Go] Interface

by llHoYall 2021. 10. 17.

An interface is an abstract concept which enables polymorphism in Go.

An interface type is defined as a set of method signatures.

A value of interface type can hold any value that implements those methods.

An interface increases decoupling so helps you write clean code.

Interface Declaration

An interface is declared as a type.

type INTERFACE_NAME interface{
  METHOD_PROTOTYPES
}

 

The zero value of an interface is nil. In other words, it doesn't have a valid address.

func main() {
  var test interface{}  // empty interface
  fmt.Println(test)
  // <nil>
}

An interface is empty if it has no functions at all.

An empty interface can hold any type.

 

The interface values can be equal if any of the conditions shown below are true.

  • Both are nil.
  • Have the same underlying concrete values and the same dynamic type.
func isEqual(x interface{}, y interface{}) {
  if (x == y) {
    fmt.Println("Equal")
  } else {
    fmt.Println("Inequal")
  }
}
 
func main() {
  var a interface{}
  var b interface{}
     
  isEqual(a, b)  // Equal
     
  var c interface{} = "A string"
  var d interface{} = "A string"
     
  isEqual(c, d)  // Equal
}

Methods of an Interface

type testInterface interface {
  methodWithoutParameter()
  methodWithParameter(float64)
  methodWithReturn() string
}

type testType int

func (t testType) methodWithoutParameter() {
  fmt.Println("methodWithoutParameter is called")
}

func (t testType) methodWithParameter(f float64) {
  fmt.Println("methodWithParameter is called with", f)
}

func (t testType) methodWithReturn() string {
  return "methodWithReturn is called"
}

func (t testType) methodNotInInterface() {
  fmt.Println("methodNotInInterface is called")
}

func main() {
  var test testInterface
  test = testType(7)
  
  test.methodWithoutParameter()
  // methodWithoutParameter is called
  
  test.methodWithParameter(3.14)
  // methodWithParameter is called with 3.14
  
  fmt.Println(test.methodWithReturn())
  // methodWithReturn is called
  
  // test.methodNotInInterface  // Error: undefined
}

As you can see in the above example, you can use all kinds of methods for an interface.

But, you can't use methods that are not in an interface.

Multiple Interfaces

Multiple interfaces can be implemented at the same time.

type walker interface {
  walk() string
}

type runner interface {
  run() string
}

type person struct {
  name string
}

func (p person) walk() string {
  return "walking"
}

func (p person) run() string {
  return "running"
}

func main() {
  var p = person{"HoYa"}
  var w walker = p
  var r runner = p
  
  fmt.Println(w.walk())
  // walking
  fmt.Println(r.run())
  // running
}

Type Assertion

Type assertion is a way to get the underlying value an interface holds.

This means if an interface variable is assigned a string then the underlying value it holds is the string.

type person struct {
  name string
}

func main() {
  var test interface{} = person{"HoYa"}
  fmt.Println(test.(person))
  // {HoYa}
}

 

If type assertions are used in the context of receiving one return value, the program will panic during runtime if the type to assert with the original type does not match.

type person struct {
  name string
}

type animal struct {
  name string
}

func main() {
  var test interface{} = person{"HoYa"}
  fmt.Println(test.(animal))  // Panic!
}

 

If type assertions are used in the context of receiving multiple return values, an optional second value is returned indicating whether the type assertions are successful.

Therefore, even if type assertions fail, panic does not occur.

The second return value is of bool type and has a value of true if the original type and the type to assert match, otherwise a false value.

type person struct {
  name string
}

type animal struct {
  name string
}

func main() {
  var testPerson interface{} = person{"HoYa"}
  testAnimal, ok := testPerson.(animal)
  if ok {
    fmt.Println("Type assertion successes")
    fmt.Println(testAnimal.name)
  } else {
    fmt.Println("Type assertion fails")
  }
  // Type assertion fails
}

Functions with an Interface

Interfaces can be passed to functions just like any other type.

func testFunc(i interface{}) {
  fmt.Printf("%T\n", i)
}

func main() {
  var strInterface interface{} = "Test"
  var intVar int = 7
  testFunc(strInterface)  // string
  testFunc(intVar)  // int
}

'Go' 카테고리의 다른 글

[Go] Linked List  (0) 2021.10.20
[Go] Functions  (0) 2021.10.19
[Go] Method  (0) 2021.10.17
[Go] Slice  (0) 2021.10.16
[Go] Package  (0) 2021.10.16

댓글