我应该能够对字符串映射的切片进行类型断言吗?

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

Should I be able to type assert a slice of string maps?

问题

我正在使用Go NSQ库接收一条消息,其中一个字段是map[string]string的切片。我觉得我应该能够将这个字段类型断言为value.([]map[string]string),但是它失败了,我无法确定这是否是预期的结果。

以下代码片段复制了这种行为:https://play.golang.org/p/qcZM880Nal

为什么这个类型断言会失败?

英文:

I am receiving a message using the Go NSQ library where a field is a slice of map[string]string's. I feel like I should be able to type assert this field as value.([]map[string]string) but it's failing and I can't tell if this is expected or not.

This snippet replicates the behavior https://play.golang.org/p/qcZM880Nal

Why does this type assertion fail?

答案1

得分: 2

这在常见问题解答中有简要介绍。

类型[]interface{}[]map[string]string在内存中有两种不同的表示方式。它们之间没有直接的转换方法。

此外,即使允许转换,你应该注意,你不能成功地断言为不同的基本类型(http://play.golang.org/p/zMp1qebIZZ)。你只能断言为原始类型或另一种接口类型,

// panics
var i interface{} = int32(42)
_ = i.(int64)
英文:

This is covered briefly here in the FAQ.

The types []interface{} and []map[string]string have two different representation in memory. There is no direct way to convert between them.

Also, even when a conversion is allowed, you should note that you can't successfully assert to a different basic type at all (http://play.golang.org/p/zMp1qebIZZ). You can only assert to the original type, or another type of interface,

// panics
var i interface{} = int32(42)
_ = i.(int64)

答案2

得分: 1

转换并不像Jim的答案中描述的那样起作用。然而,如果你确实拥有你所声称的类型,并且你所声明的接口只是interface{},那么类型断言就可以正常工作。我不想猜测为什么另一种方法不起作用,但我认为这是因为你必须以两个阶段解包它,因为切片中的map[string]string实际上被视为一些interface{}本身。这是一个例子:

package main

import "fmt"

func main() {
    var value interface{}

    value = []map[string]string{{"address": string("this is interface literal")}}
    // value = []map[string]string{{"address": "this is map literal"}}
    
    AssertIt(value)
}

func AssertIt(value interface{}) {
    if str, ok := value.([]map[string]string); ok && len(str) > 0 {
        fmt.Println(str[0]["address"])
    } else {
        fmt.Println("nope")
    }
}

链接:https://play.golang.org/p/hJfoh_havC

英文:

The conversion referred to doesn't work as described in Jim's answer. However, if you actually have the type you claim, and the interface you state it implements is just interface{} then the type assertion works fine. I don't want to speculate on the details of why the other doesn't work but I believe it's because you would have to unbox it in two phases as the map[string]string's inside the slice are actually being viewed as some interface{} themselves. Here's an example;

package main

import "fmt"

func main() {
	var value interface{}

	value = []map[string]string{{"address": string("this is interface literal")}}
	// value = []map[string]string{{"address": "this is map literal"}}
	
	AssertIt(value)

	
}

func AssertIt(value interface{}) {
	if str, ok := value.([]map[string]string); ok && len(str) > 0 {
		fmt.Println(str[0]["address"])
	} else {
		fmt.Println("nope")
	}
}

https://play.golang.org/p/hJfoh_havC

答案3

得分: 0

你可以通过在2022年进行反射来实现。

res := `[
		{
		 "name": "jhon",
		 "age": 35
		},
		 {
		 "name": "wang",
		 "age": 30
		}
	 ]`
// res := `{
// 	"name": "jhon",
// 	"age": 35
// }`
var rst any
err := json.Unmarshal([]byte(res), &rst)
if err != nil {
	panic(err)
}
t := reflect.TypeOf(rst).Kind()
fmt.Println(t)
英文:

you can do it by reflect in 2022

res := `[
		{
		 "name": "jhon",
		 "age": 35
		},
		 {
		 "name": "wang",
		 "age": 30
		}
	 ]`
// res := `{
// 	"name": "jhon",
// 	"age": 35
// }`
var rst any
err := json.Unmarshal([]byte(res), &rst)
if err != nil {
	panic(err)
}
t := reflect.TypeOf(rst).Kind()
fmt.Println(t)

huangapple
  • 本文由 发表于 2015年9月12日 03:37:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/32530952.html
匿名

发表评论

匿名网友

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

确定