英文:
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")
	}
}
答案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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论