我刚刚意识到可以在一条语句中执行映射查找和类型/接口(interface)断言。
m := map[string]interface{}{
"key": "the value",
}
if value, ok := m["key"].(string); ok {
fmt.Printf("value exists and is a string: %s\n", value)
} else {
fmt.Println("value does not exist or is not a string")
}
这被认为是不好的吗? 我还没有看到任何官方文档对此发表评论。
编辑:我知道这段代码无法区分“键不存在”和“值类型不正确”。
edit2:咳咳,else 子句中的打印不正确:(
最佳答案
您所做的确实有效,因为您使用了 type assertion 的特殊逗号-ok 习语如果断言不成立,它不会 panic ,因为映射可以用不在其中的键索引(这将导致映射值类型的零值)。
的确,使用这个你无法判断键是否在映射中,或者它是但它的值为 nil
,但你已经怀疑这一点就好像断言没有等等,你打印“值不存在或不是字符串”。
要测试所有“角落”案例,请参阅此示例:
m := map[string]interface{}{
"key": "the value",
"key2": 2,
"key3": nil,
// "key4":"", // Uncommented on purpose
}
for _, k := range []string{"key", "key2", "key3", "key4"} {
if value, ok := m[k].(string); ok {
fmt.Printf("[key: %s] value exists and is a string: %s\n", k, value)
} else {
fmt.Printf("[key: %s] value does not exist or is not a string: %s\n",
k, value)
}
}
输出(在 Go Playground 上尝试):
[key: key] value exists and is a string: the value
[key: key2] value does not exist or is not a string:
[key: key3] value does not exist or is not a string:
[key: key4] value does not exist or is not a string:
所以基本上你可以使用它,它不会发生任何坏事(例如 panic 或内存泄漏),只需要知道它的限制(例如你无法获得与 关联的值“key2"
因为它不是 string
类型)。
如果您的目的是获取键的值(如果它存在且类型为 string
),那么这正是您的代码所做的。尽管您应该避免在需要的地方使用数据结构和构造,因为在大型项目中更难理解和维护。
我的意思是,例如,如果在您的代码中的某个时刻,您希望键 "somekey"
具有关联的 string
值,但它没有,您不会立即知道为什么会这样;是因为映射不包含该键,还是因为它包含但具有错误类型的值(或者该值甚至可能是 nil
)?需要进一步测试/调试以追查根本原因。
关于dictionary - 是 "bad form"在一条语句中进行map lookup和type assertion吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46300164/