Do Not Confuse Type Conversion and Type Assertion

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 :

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:

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”)
}

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:

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

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

--

--

DevOps / SRE & Software & Architect & Linux Geek — http://baturorkun.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store