How to determine an interface{} value's "real" type?
Solution 1
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.
Solution 2
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.")
}
Solution 3
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.
Solution 4
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)
}
}
Solution 5
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
![cc young](https://i.stack.imgur.com/lIJyE.png?s=256&g=1)
cc young
semi-retired, living in Sihanoukville, Cambodia open for: Postgres consulting IT training in Cambodia
Updated on July 08, 2022Comments
-
cc young almost 2 years
I have not found a good resource for using
interface{}
types. For examplepackage 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?
-
cc young about 13 yearsthank you for that. but still not quite there. in the example, how to I coerce var w into an int?
-
cc young about 13 yearsyou're absolutely right! thanks! do you have any insight on types string representations of types?
-
jimt about 13 yearsMue'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.
-
cc young about 13 yearsright. had forgotten syntax var.(type), which is sneaky and cool
-
Dmitri Goldring over 10 yearsCheck out
reflect.TypeOf
. -
Dave C over 9 yearsAnd 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 you can just use
fmt
's "%T" format instead of directly usingreflect
. -
C4d over 5 years@DmitriGoldring That at least answers the question in the topics title. This answer not. Thank you very much.