golang

Golang Type Assertion Examples

When working with interfaces, there are times when you need to extract the underlying values of an interface variable. In this circumstance, the type assertion is implemented. Go’s type assertion mechanism allows us to safely extract and works with the actual values that are stored in an interface variable. In other words, it provides a way to access the actual value that is stored in the interface which enables us to perform the type-specific operations. In this article, we will explore the concept of type assertion in Go with examples and handle it safely to avoid panic.

Example 1: Golang Correct Type Assertion

Type assertion is used here to extract the underlying concrete value from an interface value. The following is the code of accurate type assertion results:

package main
import "fmt"
func main() {
    var x interface{}
    x = 90
    interfaceVal := x.(int)
    fmt.Println(interfaceVal)
}

In the code, we have an interface variable “x” that holds the value of 90. Then, we assert that the underlying value of “x” is of “int” type and assign it to the “interfaceVal” variable by performing the “interfaceVal:= x.(int)” statement.  If the assertion is successful, the value is assigned to “interfaceVal”, and the program continues the execution. A runtime error takes place if the assertion is invalid because the value that is being claimed is not an “int”.  Finally, fmt.Println(interfaceVal) prints the value of “interfaceVal” which, in this case, is 90.

The following output confirms that the type assertion is successful, and the value of 90 is extracted:

 

Example 2: Golang Type Assertion Panic Case

Conversely, the type assertion which is wrong in Go causes panic. An error that cannot be seen beforehand is panic. The following programs generate panic because of the wrong assertion:

package main
import "fmt"
func main() {
    var myInterface interface{} = "Excellent"
    str := i.(string)
    fmt.Println(str)
    str, ok := i.(string)
    fmt.Println(str, ok)
    fl, ok := i.(float64)
    fmt.Println(fl, ok)
    fl = i.(float64)
    fmt.Println(fl)
}

In the code, the interface{} variable named “myInterface” is declared and is assigned with the “Excellent” value. The interface{} type is a special type in Go that can hold the values of any type. Then, the first type assertion which is “str:= i.(string)” seeks to assert the actual value of myInterface’s type string and allocates it to the “str” variable.

Similarly, the second type assertion which is fl = i.(float64) is performed which is a non-conditional assertion. It assumes that the underlying value of “myInterface” is of “float64” type. However, since the value is actually a string, a runtime panic occurs with an error message that indicates the failed assertion.

The output displays the correct assertions result, and the assertion causes panic:

Example 3: Golang Type Assertion with Error Checking

Additionally, the type assertions can also be combined with error checking. As a result, we may generate a type assertion and check to see if it is accurate.  We provided a code that performs the type assertion along with the error checking:

package main
import (
    "fmt"
)
func main() {  
    var val interface{} = 19990
    var val1 int = val.(int)   
    fmt.Println(val1)
    val2, test := val.(string)
    if test {
        fmt.Println("String Value Exist!")
        fmt.Println(val2)
    } else {
        fmt.Println("String value not Exist!")
    }
}

In the code, we declare a “val” interface variable and assign it with the value of 19990 which is an “int”. Then, we use the type assertion to extract the underlying “int” value from “val” and assign it to the “val1” variable.

Next, we perform a type assertion again. But this time, we attempt to assert the value as a string. Since the underlying value of “val” is an “int”, the type assertion fails. The value set aside for the “val2” variable is the string type’s value of zero or an empty string. Since the assertion fails, the test Boolean variable is false which indicates that the type assertion is unsuccessful.

The expected output is retrieved where it shows the type assertion to “int” is successful, and the type assertion to string fails:

Example 4: Golang Type Assertion to Avoid Panic

Within Go, the interface value and a Boolean value are returned by the type assertion statement. So, we can prevent panic if the data type differs from the type and get the Boolean value. Here, we go with the following code to avoid panic in type assertion:

package main
import "fmt"
func main() {
  var x interface{}
  x = 14
  interfaceValue, booleanValue := x.(int)
  fmt.Println("Value of Interface :", interfaceValue)
  fmt.Println("Value of Boolean :", booleanValue)
}

In the code, we begin by declaring an interface variable “x”.  The value 14 is assigned to “x” which is of “int” type. The type of “x” is inferred as “int” as well. Then, the “interfaceValue, booleanValue := x.(int)” performs a type assertion to extract the underlying “int” value from “x”. The extracted value is stored in the “interfaceValue” variable where “booleanValue” denotes whether or not the type assertion is valid.  In this case, the type assertion is successful since “x” contains an “int” value. Thus, “interfaceValue” contains the value of 14, and the “booleanValue” is true.

In the following demonstration, the type assertion to “int” is successful, and the output that extracts the value of 14 is displayed along with the Boolean value of true:

Example 5: Golang Type Assertion Using “Comma, Ok” Idiom

However, to avoid panics in type assertions in Go, we can use the comma-ok idiom, also known as the “comma, ok” idiom. This idiom allows us to perform a type assertion and checks if the assertion is successful using a Boolean flag. Consider the example code which is demonstrated in the following to handle the type assertion panic with the “ok” comma method:

package main
import (
    "fmt"
)  
func main() {    
    var verifyInterface interface{} = 12.22
    checkType1 := verifyInterface.(float64)
    fmt.Println(checkType1)
    checkType2, ok := verifyInterface.(string)
    if ok {
        fmt.Println("Assertion is Accurate!")
        fmt.Println(checkType2)
    } else {
        fmt.Println("Assertion is Wrong!")
    }
}

In the code, we declare an interface variable which is “verifyInterface” and assign a numerical value which is a floating-point number. The type of “verifyInterface” is inferred as “float64”. Then, we perform a type assertion to extract the underlying “float64” value from “verifyInterface” and assign it to “checkType1”. Since “verifyInterface” indeed contains a “float64” value, the type assertion is successful, and “checkType1” holds the value of 12.22.

After that, we proceed to the next section which demonstrates the type assertion with an additional Boolean check. The “checkType2, ok := verifyInterface.(string)” attempts to extract the string value from “verifyInterface” and assigns it to “checkType2”. The “ok” Boolean variable indicates whether or not the type assertion isvalid. In this case, the type assertion fails because “verifyInterface” does not contain a string value. Therefore, “ok” is false.

The output represents that the “float64” assertion is successful. However, the type assertion to a string fails which results in the “Assertion is Wrong!” message:

 

Conclusion

We learned the distinct examples of type assertion in Go. We also learned the examples to avoid panics and to gracefully handle the cases when the type assertion fails. Now, we will be able to work with interfaces more freely and productively in Go by comprehending and properly utilizing the type assertion.

About the author

Kalsoom Bibi

Hello, I am a freelance writer and usually write for Linux and other technology related content