Sobes.tech
Middle

How to check the type of a variable in Go at runtime?

sobes.tech AI

Answer from AI

In Go, the runtime type of a variable can be checked in several ways:

  1. Using type assertion: Suitable for checking a specific type of an interface variable.

    package main
    
    import "fmt"
    
    func main() {
        var i interface{} = "hello"
    
        s, ok := i.(string) // Attempt to assert i as a string
        if ok {
            fmt.Printf("Variable i has type string: %s\n", s)
        } else {
            fmt.Println("Variable i is not of type string")
        }
    }
    
  2. Using type switch: Suitable for checking multiple possible types of an interface variable.

    package main
    
    import "fmt"
    
    func main() {
        var t interface{}
    
        switch tt := t.(type) { // tt will have a specific type from the cases
        case int:
            fmt.Printf("Variable has type int: %d\n", tt)
        case string:
            fmt.Printf("Variable has type string: %s\n", tt)
        case bool:
            fmt.Printf("Variable has type bool: %t\n", tt)
        case nil:
            fmt.Println("Variable has value nil")
        default:
            fmt.Printf("Unknown type: %T\n", tt) // tt will have type interface{}
        }
    
        t = 123
        switch tt := t.(type) {
        case int:
            fmt.Printf("Variable has type int: %d\n", tt)
        case string:
            fmt.Printf("Variable has type string: %s\n", tt)
        case bool:
            fmt.Printf("Variable has type bool: %t\n", tt)
        case nil:
            fmt.Println("Variable has value nil")
        default:
            fmt.Printf("Unknown type: %T\n", tt)
        }
    }
    
  3. Using the reflect package: Allows obtaining information about the type and value of a variable at runtime. Used when types are unknown at compile time or for more complex checks.

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func main() {
        var x float64 = 3.4
        v := reflect.ValueOf(x) // Get reflection value
    
        fmt.Println("Type:", v.Type())                 // Outputs "Type: float64"
        fmt.Println("Kind:", v.Kind())                 // Outputs "Kind: float64"
    
        y := "hello"
        vv := reflect.ValueOf(y)
        fmt.Println("Type:", vv.Type())               // Outputs "Type: string"
        fmt.Println("Kind:", vv.Kind())               // Outputs "Kind: string"
    
        z := []int{1, 2, 3}
        vvv := reflect.ValueOf(z)
        fmt.Println("Type:", vvv.Type())             // Outputs "Type: []int"
        fmt.Println("Kind:", vvv.Kind())             // Outputs "Kind: slice"
    }
    

The reflect package is more powerful but also more complex to use. Type assertion and type switch are preferred for simple type checks of interface variables, as they are safer and type-oriented.