Do Not Confuse Type Conversion and Type Assertion

Batur Orkun
3 min readJun 26, 2019

--

There are two ways to cast values in GoLang because GoLang is a static type language but there is an interface type for unclear types. The usage of interfaces in GoLang is a little bit tricky. An interface isn’t just a collection of method contracts. We can create a variable of its type. An interface does not have a static value, rather it points to a dynamic value. This feature provides easy programming like script languages when it is necessary. For example, we can need unclear types of function parameters. So you should use interface type on your function parameters.

func Test(v interface{}) {

}

I want to explain by full example code.

package main

import (
“fmt”
)

func Test(i interface{},s interface{}) {
fmt.Printf(“Type(i): %T , Type(s): %T”, i,s)
}

func main() {
Test(5, “batur”)
}

Output :

Type(i): int , Type(s): string

Parameters of the Test function is an interface type. You can give any type of value. This is called as Duck Typing.

“Duck Typing” says: If it walks like a duck, and quacks like a duck, then it must be a duck.

I should give you a piece of advice. If you don’t need Duck Typing, do not use. These approaches can make increase your runtime error.

Now you need the value of parameters. So you must use “reflect” package.

package main

import (
“fmt”
“reflect”
)

func Test(i interface{},s interface{}) {

iVal := reflect.ValueOf(i)
sVal := reflect.ValueOf(s)

fmt.Printf(“Type(i): %T , Type(s): %T \n”, i,s)
fmt.Printf(“Type(iVal): %T , Type(sVal): %T \n”, iVal,sVal)
fmt.Printf(“Value(i): %v , Value(s): %v \n”, iVal,sVal)
}

func main() {
Test(5, “batur”)
}

Output:

Type(i): int , Type(s): string 
Type(iVal): reflect.Value , Type(sVal): reflect.Value
Value(i): 5 , Value(s): batur

You should notice that I use “%v” to print values because I have no integer and string type values. If you try using “%i”, you will get an error. I can get values by “reflect” package but generally, we need static and real type variables. For example, you want to use integer value in math operations. You cannot use iVal in math operations. You must assert to an integer.

Last version of our script:

package main

import (
“fmt”
)

func Test(i interface{},s interface{}) {

var iVal int
var sVal string

iVal = i.(int)
sVal = s.(string)

fmt.Printf(“Type(i): %T , Type(s): %T \n”, i,s)
fmt.Printf(“Type(iVal): %T , Type(sVal): %T \n”, iVal,sVal)
fmt.Printf(“Value(i): %d , Value(s): %s \n”, iVal,sVal)
}

func main() {
Test(5, “batur”)
}

Type(i): int , Type(s): string 
Type(iVal): int , Type(sVal): string
Value(i): 5 , Value(s): batur

Now you can see real types. “iVal” is an integer and “sVal” is a string. That is the “type assertion”.

v = t.(Type) // type assertion

Type conversion is different and simple. Conversion is about change value type. There are some functions same named with the type name.

v = Type(t) // type conversion

Example :

package main

import (
“fmt”
“math”
)

func main() {
var x = 3
var f float64 = math.Sqrt(float64(x))
var i uint = uint(f)
fmt.Printf(“Values: %v , %v, %v”, x, f, i)
}

Output:

Values: 3 , 1.7320508075688772, 1

If you have a string value, you cannot use “int” or “uint” functions. There is “strconv” library that Linux lovers know well. The easiest way is to use the strconv.Atoi() function.

package main

import (
“fmt”
“strconv”
“log”
)

func main() {

var s string

s = “5”

var i int

i,err := strconv.Atoi(s)

if err != nil {
log.Fatalf(“Error on conversion %s”, s)
}

fmt.Printf(“Values: %s , %d \n”, s, i)

fmt.Printf(“Types: %T , %T”, s, i)
}

Output:

Values: 5 , 5 
Types: string , int

Conclusively, I can say that conversion is used when you are dealing with types, Assertion is used when you’re dealing with an interface.

Is it understandable and easy? See you later. :)

--

--