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