处理地图中的零值

Posted

技术标签:

【中文标题】处理地图中的零值【英文标题】:Handling nil values in a map 【发布时间】:2021-06-05 16:27:21 【问题描述】:

我想用地图中的值创建一个结构。

这是一个sn-p:

        log := &Log
            Facility:  parts["facility"].(int),
            Severity:  parts["severity"].(int),
            Timestamp: parts["timestamp"].(time.Time),
            Hostname:  parts["hostname"].(string),
            AppName:   parts["appName"].(string),
            Client:    parts["client"].(string),
            Priority:  parts["priority"].(int),
            Message:   parts["message"].(string),
        

问题是,如果其中一个值为 nil,则会发生恐慌。所以我想做这样的事情:

Facility:  parts["facility"] != nil ? parts["facility"].(int) : 0

但这不是一个有效的语法。

我是否必须分别检查每个键才能处理 nil 情况?

【问题讨论】:

1>如果事先知道数据类型,那么您必须使用结构或结构映射 2> data,ok:=parts["facility"]; if ok && data!=nil value=data.(int) golang.org/doc/faq#Does_Go_have_a_ternary_form 见What is the idiomatic Go equivalent of C's ternary operator? 【参考方案1】:

你可以这样做:

 log := &Log
 log.Facility, _ = parts["facility"].(int)
 log.Severity, _ = parts["severity"].(int)
  ...

这将使用类型断言的双值形式,其中第二个值指示类型断言是否有效,然后您将忽略该值,因此如果映射没有,则使用零值初始化结构成员包含密钥,或者如果密钥不是所需的类型。

【讨论】:

从技术上讲,这是类型断言的 2 值形式,而不是映射查找。映射中的 nil 接口值被传递给断言,然后断言可以将接口断言为所需的零值。 @JimB,你是对的我修正了答案【参考方案2】:

如果您愿意,可以为这些类型编写包装器:

func toInt(x interface) int 
    if i, ok := x.(int); ok 
        return i
    
    return 0 // Or what you would like to have as a default.

如果要使用类型的默认值,可以缩短:

func toInt(x interface) int 
    i, _ := x.(int)
    return i

这将使它看起来像这样:

    log := &Log
        Facility:  toInt(parts["facility"]),
        Severity:  toInt(parts["severity"]),
        Timestamp: toTime(parts["timestamp"]),
        Hostname:  toString(parts["hostname"]),
        AppName:   toString(parts["appName"]),
        Client:    toString(parts["client"]),
        Priority:  toInt(parts["priority"]),
        Message:   toString(parts["message"]),
    

你可以更进一步,在本地编写你的转换函数:

var parts map[string]interface

// ...

i := func(name string) int 
    i, _ := parts[name].(int)
    return i


s := func(name string) string 
    s, _ := parts[name].(string)
    return s


t := func(name string) time.Time 
    t, _ := parts[name].(time.Time)
    return t


log := &Log
    Facility:  i("facility"),
    Severity:  i("severity"),
    Timestamp: t("timestamp"),
    Hostname:  s("hostname"),
    AppName:   s("appName"),
    Client:    s("client"),
    Priority:  i("priority"),
    Message:   s("message"),

【讨论】:

以上是关于处理地图中的零值的主要内容,如果未能解决你的问题,请参考以下文章

Python中的零对数

用中值替换numpy数组中的零

用先前的非零值替换向量中的所有零

Matlab - 求数组的零值与过零点索引

导入 cvs 但基于特定列中的零删除行[重复]

编译器是不是应该正确地将 bool 中的任意非零值解释为 true?