如何确定接口{}值的“实”类型?

我还没有找到使用 interface{}类型的好资源

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

你知道一个使用围棋 interface{}的好的介绍吗?

具体问题:

  • 我怎么才能得到“真正的”w 呢?
  • 有什么方法可以得到类型的字符串表示形式吗?
  • 是否有任何方法可以使用类型的字符串表示形式来 转换一个值?
148931 次浏览

你的例子确实有用,这是一个简化版本。

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

它使用 类型断言

你也可以做类型转换:

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.")
}

您可以使用反射(reflect.TypeOf())来获取事物的类型,它给出的值(Type)有一个可以打印的字符串表示(String方法)。

类型开关也可以与反射材料一起使用:

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

下面是一个同时使用开关和反射解码通用映射的示例,所以如果您不匹配该类型,请使用反射来找出它,然后在下次添加该类型。

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

我将提供一种返回布尔值的方法,它基于将反射类型的参数传递给本地类型接收器(因为我找不到任何类似的东西)。

首先,我们声明我们的匿名类型的型别。值:

type AnonymousType reflect.Value

然后我们为我们的本地类型 Anonymous ousType 添加一个构建器,它可以接受任何潜在的类型(作为一个接口) :

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

然后,我们为 Anonymous ousType 结构添加一个函数,它针对一个反射断言:

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

这使我们可以调用以下方式:

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

在这里可以看到一个更长的工作版本: https://play.golang.org/p/EIAp0z62B7

获取类型的字符串表示形式有多种方法。开关也可以用于用户类型:

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

连接到操场: https://play.golang.org/p/VDeNDUd9uK6

你可以用

  1. Printf (“% T”,接口{})
  2. 反映。类型
  3. 值(x)。种类()

- > 反映:

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

产出:

bool
string
int
float64
[]string

- > 反映. ValueOf (x) . Kind ()

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

来源: 宅男之宅