156

I have not found a good resource for using interface{} types. For example

package main

import "fmt"

func weirdFunc(i int) interface{} {
    if i == 0 {
        return "zero"
    }
    return i
}
func main() {
    var i = 5
    var w = weirdFunc(5)

    // this example works!
    if tmp, ok := w.(int); ok {
        i += tmp
    }

    fmt.Println("i =", i)
}

Do you know of a good introduction to using Go's interface{}?

specific questions:

  • how do I get the "real" Type of w?
  • is there any way to get the string representation of a type?
  • is there any way to use the string representation of a type to convert a value?
peterSO
  • 158,998
  • 31
  • 281
  • 276
cc young
  • 18,939
  • 31
  • 90
  • 148

8 Answers8

166

You also can do type switches:

switch v := myInterface.(type) {
case int:
    // v is an int here, so e.g. v + 1 is possible.
    fmt.Printf("Integer: %v", v)
case float64:
    // v is a float64 here, so e.g. v + 1.0 is possible.
    fmt.Printf("Float64: %v", v)
case string:
    // v is a string here, so e.g. v + " Yeah!" is possible.
    fmt.Printf("String: %v", v)
default:
    // And here I'm feeling dumb. ;)
    fmt.Printf("I don't know, ask stackoverflow.")
}
themue
  • 7,626
  • 2
  • 25
  • 28
  • thank you for that. but still not quite there. in the example, how to I coerce var w into an int? – cc young Jun 16 '11 at 15:11
  • 3
    Mue's example does the same thing, but in a type switch instead of an if statement. In the 'case int', 'v' will be an integer. in 'case float64', 'v' will be a float64, etc. – jimt Jun 16 '11 at 16:48
  • right. had forgotten syntax var.(type), which is sneaky and cool – cc young Jun 16 '11 at 18:56
120

Your example does work. Here's a simplified version.

package main

import "fmt"

func weird(i int) interface{} {
    if i < 0 {
        return "negative"
    }
    return i
}

func main() {
    var i = 42
    if w, ok := weird(7).(int); ok {
        i += w
    }
    if w, ok := weird(-100).(int); ok {
        i += w
    }
    fmt.Println("i =", i)
}

Output:
i = 49

It uses Type assertions.

peterSO
  • 158,998
  • 31
  • 281
  • 276
65

You can use reflection (reflect.TypeOf()) to get the type of something, and the value it gives (Type) has a string representation (String method) that you can print.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • 11
    And if you just want to get a string or a type (e.g. for printing in the default block of a type switch link in [Mue's answer](http://stackoverflow.com/a/6373523/55504) you can just use `fmt`'s "%T" format instead of directly using `reflect`. – Dave C Mar 10 '15 at 16:49
18

Here is an example of decoding a generic map using both switch and reflection, so if you don't match the type, use reflection to figure it out and then add the type in next time.

var data map[string]interface {}

...

for k, v := range data {
    fmt.Printf("pair:%s\t%s\n", k, v)   

    switch t := v.(type) {
    case int:
        fmt.Printf("Integer: %v\n", t)
    case float64:
        fmt.Printf("Float64: %v\n", t)
    case string:
        fmt.Printf("String: %v\n", t)
    case bool:
        fmt.Printf("Bool: %v\n", t)
    case []interface {}:
        for i,n := range t {
            fmt.Printf("Item: %v= %v\n", i, n)
        }
    default:
        var r = reflect.TypeOf(t)
        fmt.Printf("Other:%v\n", r)             
    }
}
h4ck3rm1k3
  • 2,060
  • 22
  • 33
9

There are multiple ways to get a string representation of a type. Switches can also be used with user types:

var user interface{}
user = User{name: "Eugene"}

// .(type) can only be used inside a switch
switch v := user.(type) {
case int:
    // Built-in types are possible (int, float64, string, etc.)
    fmt.Printf("Integer: %v", v)
case User:
    // User defined types work as well  
    fmt.Printf("It's a user: %s\n", user.(User).name)
}

// You can use reflection to get *reflect.rtype
userType := reflect.TypeOf(user)
fmt.Printf("%+v\n", userType)

// You can also use %T to get a string value
fmt.Printf("%T", user)

// You can even get it into a string
userTypeAsString := fmt.Sprintf("%T", user)

if userTypeAsString == "main.User" {
    fmt.Printf("\nIt's definitely a user")
}

Link to a playground: https://play.golang.org/p/VDeNDUd9uK6

Eugene Kulabuhov
  • 2,349
  • 1
  • 26
  • 25
8

Type switches can also be used with reflection stuff:

var str = "hello!"
var obj = reflect.ValueOf(&str)

switch obj.Elem().Interface().(type) {
case string:
    log.Println("obj contains a pointer to a string")
default:
    log.Println("obj contains something else")
}
Nikolai Koudelia
  • 2,494
  • 1
  • 26
  • 28
3

I'm going to offer up a way to return a boolean based on passing an argument of a reflection Kinds to a local type receiver (because I couldn't find anything like this).

First, we declare our anonymous type of type reflect.Value:

type AnonymousType reflect.Value

Then we add a builder for our local type AnonymousType which can take in any potential type (as an interface):

func ToAnonymousType(obj interface{}) AnonymousType {
    return AnonymousType(reflect.ValueOf(obj))
}

Then we add a function for our AnonymousType struct which asserts against a reflect.Kind:

func (a AnonymousType) IsA(typeToAssert reflect.Kind) bool {
    return typeToAssert == reflect.Value(a).Kind()
}

This allows us to call the following:

var f float64 = 3.4

anon := ToAnonymousType(f)

if anon.IsA(reflect.String) {
    fmt.Println("Its A String!")
} else if anon.IsA(reflect.Float32) {
    fmt.Println("Its A Float32!")
} else if anon.IsA(reflect.Float64) {
    fmt.Println("Its A Float64!")
} else {
    fmt.Println("Failed")
}

Can see a longer, working version here:https://play.golang.org/p/EIAp0z62B7

daino3
  • 4,386
  • 37
  • 48
3

You can use

  1. Printf("%T", interface{})
  2. reflect.TypeOf
  3. reflect.ValueOf(x).Kind()

-> reflect:

 func typeofobject(x interface{}){
        fmt.Println(reflect.TypeOf(x))
 }

-> Printf()

 // Golang program to find the variable type
    package main
    
    // importing required packages
    import (
      "fmt"
    )
    
    // main function
    func main() {
      f := true
      st := ""
      a := 1
      d := 1.0
      arr := []string{"Go", "Is", "Fun"}
    
      fmt.Printf("%T\n", f)
      fmt.Printf("%T\n", st)
      fmt.Printf("%T\n", a)
      fmt.Printf("%T\n", d)
      fmt.Printf("%T\n", arr)
    }

OUTPUT:

bool
string
int
float64
[]string

-> reflect.ValueOf(x).Kind())

func typeofobject(x interface{}){
    fmt.Println(reflect.ValueOf(x).Kind())
}

source: geeks-for-geeks

Ayush
  • 373
  • 4
  • 12