Types 如何确定接口{}值';s";“真正的”;类型?

Types 如何确定接口{}值';s";“真正的”;类型?,types,type-conversion,go,Types,Type Conversion,Go,我还没有找到使用接口{}类型的好资源。比如说 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.(in

我还没有找到使用
接口{}
类型的好资源。比如说

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)
}
你知道关于使用Go的
接口{}
的一个很好的介绍吗

具体问题:

  • 我如何获得“真实”类型的w
  • 有没有办法获得类型的字符串表示形式
  • 有没有办法使用类型的字符串表示来 转换一个值

    • 您的示例确实有效。这是一个简化的版本

      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
      
      主程序包
      输入“fmt”
      func(i int)接口{}{
      如果i<0{
      返回“负”
      }
      返回i
      }
      func main(){
      变量i=42
      如果w,ok:=怪异(7)。(int);ok{
      i+=w
      }
      如果w,ok:=怪异(-100)。(int);ok{
      i+=w
      }
      fmt.Println(“i=,i)
      }
      输出:
      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")
      }
      

      下面是一个使用switch和reflection对泛型映射进行解码的示例,因此如果您不匹配类型,请使用reflection找出它,然后下次添加该类型

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

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

      首先,我们声明reflect.Value类型的匿名类型:

      type AnonymousType reflect.Value
      
      然后,我们为本地类型AnonymousType添加一个生成器,它可以接受任何潜在类型(作为接口):

      然后,我们为我们的AnonymousType结构添加了一个函数,该结构根据reflect.Kind断言:

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

      可以在此处看到更长的工作版本:

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

      var用户界面{}
      user=user{name:“Eugene”}
      //(类型)只能在开关内部使用
      开关v:=用户。(类型){
      案例int:
      //可以使用内置类型(int、float64、string等)
      fmt.Printf(“整数:%v”,v)
      案例用户:
      //用户定义的类型也可以工作
      fmt.Printf(“它是一个用户:%s\n”,user.(user).name)
      }
      //您可以使用反射来获取*reflect.rtype
      userType:=reflect.TypeOf(用户)
      fmt.Printf(“%+v\n”,用户类型)
      //您还可以使用%T获取字符串值
      fmt.Printf(“%T”,用户)
      //你甚至可以把它编成一个字符串
      userTypeAsString:=fmt.Sprintf(“%T”,用户)
      如果userTypeAsString==“main.User”{
      fmt.Printf(“\n它肯定是用户”)
      }
      

      链接到游乐场:

      谢谢你。但仍然不完全如此。在这个例子中,如何将var w强制转换为int?Mue的例子也做了同样的事情,但是是在类型开关中,而不是在if语句中。在“case int”中,“v”将是一个整数。在“case float64”中,“v”将是一个float64,等等。忘记了语法变量(type),这是鬼鬼祟祟的,很酷。你完全正确!谢谢你对类型的字符串表示有什么见解吗?请查看
      reflect.TypeOf
      @DmitriGoldring,至少回答了主题标题中的问题。这个答案不是。非常感谢。如果您只想获取字符串或类型(例如,在中的类型切换链接的默认块中打印),您可以使用
      fmt
      的“%T”格式,而不是直接使用
      reflect
      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")
      }