在一个语句中执行映射查找和类型断言是"糟糕的形式"吗?

pyt*_*tor 8 dictionary idiomatic go type-assertion

我刚刚意识到可以在一个语句中进行映射查找和类型/接口断言.

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")
}
Run Code Online (Sandbox Code Playgroud)

这被认为是坏事吗?我没有看到任何官方文件评论这一点.

编辑:我知道这段代码无法区分"密钥不存在"和"值是不正确的类型".

edit2:ahem,else子句中的print是不正确的:(

icz*_*cza 10

你实际工作的是什么,因为你使用类型断言的特殊逗号成语,如果断言不成立则不会出现恐慌,并且因为映射可以用不在其中的键索引(这将导致零地图的值类型的值).

确实如此,你无法判断键是否在地图中,或者它是,但它的值是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)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出(在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: 
Run Code Online (Sandbox Code Playgroud)

所以基本上你可以使用它,不会发生任何坏事(例如恐慌或内存泄漏),只知道它的限制(例如你不能得到相关的值,"key2"因为它不是string类型).

如果您的目的是获取密钥的值(如果密钥存在且属于类型)string,那么这就是您的代码的确切功能.虽然您应该避免在需要的地方使用数据结构和构造,因为在较大的项目中更难理解和维护.

我的意思是,例如,如果在代码中的某个时刻,您希望密钥"somekey"具有string关联的值而不是,则您不会立即知道为什么会这样; 是因为地图不包含那个键,还是因为它确实存在但是值类型错误(或者值甚至可能是nil)?需要进一步测试/调试以追查根本原因.