DEV Community

K-Sato
K-Sato

Posted on

My Journey of Go ⑥ (Interfaces)

#go

Interfaces in Go

In Go, an interface is a set of method signatures. A variable of interface type can hold any value that implements those methods.

Basics

You can declare an interface like the following code. It is basically just a list of methods.

type NAME_OF_INTERFACE interface {
    method_name1(return_type1)    
    method_name2(return_type2)
    ..........
    method_namex(return_typex)
}
Enter fullscreen mode Exit fullscreen mode

Any type that provides the methods named in an interface is treated as an implementation of that interface. No explicit declaration is required.

The empty interface

The interface type that does not specify any method is known as the empty interface. It can be defined as the following code.

interface {}
Enter fullscreen mode Exit fullscreen mode

A variable of empty interface type can hold values of any type.

package main

import "fmt"

func main(){
  var intface interface{}
  intface = 1
  fmt.Println(intface) //=> 1

  intface = "string" //=> string
  fmt.Println(intface)

  intface = []string{"Go", "Ruby", "JS"}
  fmt.Println(intface) //=>[Go Ruby JS]
}
Enter fullscreen mode Exit fullscreen mode

Interface values

A interface value is represented as a pair of a concrete value and a dynamic type.

[Value, Type]
Enter fullscreen mode Exit fullscreen mode

You can use %v to print the concrete value and %T to print the dynamic type.

package main

import "fmt"

func main(){
  var intface interface{}
  intface = 1
  fmt.Printf("%v %T\n", intface, intface) //=>1 int

  intface = "string"
  fmt.Printf("%v %T\n", intface, intface) //=> string string

  intface = []string{"Go", "Ruby", "JS"}
  fmt.Printf("%v %T\n", intface, intface) //=> [Go Ruby JS] []string
}
Enter fullscreen mode Exit fullscreen mode

Type assertions

A type assertion provides access to an interface value's underlying concrete value.

concrete_value := Interface_value.(TYPE)
Enter fullscreen mode Exit fullscreen mode

This statement above asserts that Interface_value holds the concrete type TYPE and assigns the underlying TYPE value to variable.

To check whether an interface value holds a specific type, a type assertion can return two values. the underlying value and a boolean value that reports whether the assertion succeeded.

concrete_value, ok := Interface_value.(TYPE)
Enter fullscreen mode Exit fullscreen mode
package main

import "fmt"

func main(){
  var intface interface{} = "Hello World"

  t := intface.(string)
  fmt.Println(t) //=> Hello World

  t2, ok := intface.(string)
  fmt.Println(t2, ok) //=> Hello World true

  t3, ok := intface.(float64)
  fmt.Println(t3, ok) //=> 0 false
}
Enter fullscreen mode Exit fullscreen mode

Type switches

A type switch is a construct that permits several type assertions in series.

You can declare a type switch like the following code.

switch v := x.(type) {
    case TYPE1:
    //here v has TYPE1
    case TYPE2:
    //here: v has TYPE2
    ...
    default: ...
}
Enter fullscreen mode Exit fullscreen mode

In the follwing code, the switch statement tests whether the interface value i holds a value of type int or string. In each of the int and string cases, the variable v will be of type int or string respectively and hold the value held by i.

In the default case (where there is no match), the variable v is of the same interface type and value as i.

package main

import "fmt"

func typeSwitch(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("Twice %v is %v\n", v, v*2)
    case string:
        fmt.Printf("%q is %v bytes long\n", v, len(v))
    default:
        fmt.Printf("I don't know about type %T!\n", v)
    }
}

func main() {
    typeSwitch(21) //=> Twice 21 is 42
    typeSwitch("Hello World") //=> "Hello World" is 11 bytes long
    typeSwitch(true)//=> I don't know about type bool!
}
Enter fullscreen mode Exit fullscreen mode

Implementing interfaces

Interfaces can be implemented as methods on structs like the following code.

package main

import "fmt"

 type People interface {
  intro()
 }

 type Person struct {
   name string
 }

func (rarg Person) intro() string{
  return "Hello" + " " + "I'm" + " " + rarg.name
}

func main() {
  bob := Person{"Bob"}
  fmt.Println(bob.intro()) //=> Hello I'm Bob
}
Enter fullscreen mode Exit fullscreen mode

Discussion (1)

Collapse
angelae94078470 profile image
Angela Evans

Like coins that make money, every little thing you share gives me more knowledge. I am very happy to find this article, it was very helpful to me. Thank you much for your time. taming io