我想用map中的值创建一个结构体
下面是一个片段:
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情况吗?
你可以这样做:
log := &Log{}
log.Facility, _ = parts["facility"].(int)
log.Severity, _ = parts["severity"].(int)
...
这将使用类型断言的双值形式,其中第二个值指示类型断言是否有效,然后忽略该值,因此,如果映射不包含键,或者键不是所需的类型,则使用零值初始化struct成员。
如果您愿意,可以为这些类型编写包装器:
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"),
}