如何确定interface{}值的“真实”类型?

huangapple go评论84阅读模式
英文:

How to determine an interface{} value's "real" type?

问题

我还没有找到一个好的使用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)

    // 这个例子可以工作!
    if tmp, ok := w.(int); ok {
        i += tmp
    }

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

你知道有关使用Go的interface{}的好介绍吗?

具体问题:

  • 如何获取w的“真实”类型?
  • 有没有办法获取类型的字符串表示?
  • 有没有办法使用类型的字符串表示来转换一个值?
英文:

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?

答案1

得分: 166

你也可以使用类型开关:

switch v := myInterface.(type) {
case int:
    // v 在这里是一个整数,所以可以进行 v + 1 等操作。
    fmt.Printf("整数: %v", v)
case float64:
    // v 在这里是一个浮点数,所以可以进行 v + 1.0 等操作。
    fmt.Printf("浮点数: %v", v)
case string:
    // v 在这里是一个字符串,所以可以进行 v + " Yeah!" 等操作。
    fmt.Printf("字符串: %v", v)
default:
    // 在这里我感觉很笨。 ;)
    fmt.Printf("我不知道,去问 stackoverflow 吧。")
}
英文:

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

答案2

得分: 120

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

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

输出:
i = 49

它使用了类型断言

英文:

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

package main

import &quot;fmt&quot;

func weird(i int) interface{} {
	if i &lt; 0 {
		return &quot;negative&quot;
	}
	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(&quot;i =&quot;, i)
}

Output:
i = 49

It uses Type assertions.

答案3

得分: 65

你可以使用反射(reflect.TypeOf())来获取某个东西的类型,而它所返回的值(Type)有一个字符串表示形式(String方法),你可以打印出来。

英文:

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.

答案4

得分: 18

这是一个使用switch和反射解码通用映射的示例,所以如果不匹配类型,使用反射来找出类型,然后在下次添加类型。

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)				
	}
}
英文:

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(&quot;pair:%s\t%s\n&quot;, k, v) 	

	switch t := v.(type) {
	case int:
		fmt.Printf(&quot;Integer: %v\n&quot;, t)
	case float64:
		fmt.Printf(&quot;Float64: %v\n&quot;, t)
	case string:
		fmt.Printf(&quot;String: %v\n&quot;, t)
	case bool:
		fmt.Printf(&quot;Bool: %v\n&quot;, t)
	case []interface {}:
		for i,n := range t {
			fmt.Printf(&quot;Item: %v= %v\n&quot;, i, n)
		}
	default:
		var r = reflect.TypeOf(t)
		fmt.Printf(&quot;Other:%v\n&quot;, r)				
	}
}

答案5

得分: 9

有多种方法可以获得类型的字符串表示。开关语句也可以用于用户定义的类型:

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

// .(type) 只能在开关语句内部使用
switch v := user.(type) {
case int:
	// 内置类型也可以(int、float64、string等)
	fmt.Printf("整数: %v", v)
case User:
	// 用户定义的类型也可以
	fmt.Printf("这是一个用户:%s\n", user.(User).name)
}

// 你可以使用反射来获取 *reflect.rtype
userType := reflect.TypeOf(user)
fmt.Printf("%+v\n", userType)

// 你也可以使用 %T 来获取字符串值
fmt.Printf("%T", user)

// 甚至可以将其转换为字符串
userTypeAsString := fmt.Sprintf("%T", user)

if userTypeAsString == "main.User" {
	fmt.Printf("\n这绝对是一个用户")
}

Playground链接:https://play.golang.org/p/VDeNDUd9uK6

英文:

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: &quot;Eugene&quot;}

// .(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(&quot;Integer: %v&quot;, v)
case User:
	// User defined types work as well	
	fmt.Printf(&quot;It&#39;s a user: %s\n&quot;, user.(User).name)
}

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

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

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

if userTypeAsString == &quot;main.User&quot; {
	fmt.Printf(&quot;\nIt&#39;s definitely a user&quot;)
}

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

答案6

得分: 8

类型切换也可以与反射一起使用:

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

switch obj.Elem().Interface().(type) {
case string:
    log.Println("obj包含一个指向字符串的指针")
default:
    log.Println("obj包含其他内容")
}
英文:

Type switches can also be used with reflection stuff:

var str = &quot;hello!&quot;
var obj = reflect.ValueOf(&amp;str)

switch obj.Elem().Interface().(type) {
case string:
	log.Println(&quot;obj contains a pointer to a string&quot;)
default:
	log.Println(&quot;obj contains something else&quot;)
}

答案7

得分: 3

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

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

type AnonymousType reflect.Value

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

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

然后,我们为我们的 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")
}

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

英文:

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(&quot;Its A String!&quot;)
} else if anon.IsA(reflect.Float32) {
	fmt.Println(&quot;Its A Float32!&quot;)
} else if anon.IsA(reflect.Float64) {
	fmt.Println(&quot;Its A Float64!&quot;)
} else {
	fmt.Println(&quot;Failed&quot;)
}

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

答案8

得分: 3

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

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

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

source: geeks-for-geeks

英文:

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 (
      &quot;fmt&quot;
    )
    
    // main function
    func main() {
      f := true
      st := &quot;&quot;
      a := 1
      d := 1.0
      arr := []string{&quot;Go&quot;, &quot;Is&quot;, &quot;Fun&quot;}
    
      fmt.Printf(&quot;%T\n&quot;, f)
      fmt.Printf(&quot;%T\n&quot;, st)
      fmt.Printf(&quot;%T\n&quot;, a)
      fmt.Printf(&quot;%T\n&quot;, d)
      fmt.Printf(&quot;%T\n&quot;, 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

huangapple
  • 本文由 发表于 2011年6月16日 21:13:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/6372474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定