Posted on: Written by: K-Sato
⚠️ This article was posted over 2 years ago. The information might be outdated. ⚠️

Table of Contents

Introduction

In this post, I’ll explain how interfaces work in 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 {
    methodName1(returnType11)
    methodName2(returnType12)
    ..........
    methodNamex(returnType1x)
}

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

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

Interface values

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

[Value, Type]

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
}

Type assertions

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

concreteValue := InterfaceValue.(TYPE)

This statement above asserts that InterfaceValue 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.

concreteValue, ok := InterfaceValue.(TYPE)
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
}

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: ...
}

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

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
}

About the author

I am a web-developer based somewhere on earth. I primarily code in TypeScript, Go and Ruby at work. React, RoR and Gin are my go-to Frameworks.