如何重写以下代码?
switch md.(type) {
case *amf0.EcmaArrayType:
ea := md.(*amf0.EcmaArrayType)
for k, v := range (*ea) {
log.Printf("%v = %v\n", k, v)
}
if width == 0 {width = uint16((*ea)["width"].(amf0.NumberType))}
if height == 0 {height = uint16((*ea)["height"].(amf0.NumberType))}
case *amf0.ObjectType:
ea := md.(*amf0.ObjectType)
for k, v := range (*ea) {
log.Printf("%v = %v\n", k, v)
}
if width == 0 {width = uint16((*ea)["width"].(amf0.NumberType))}
if height == 0 {height = uint16((*ea)["height"].(amf0.NumberType))}
}
对于不同的类型,它有两个完全重复的 block 。如果我在开关状态上方声明 var ea interface{}
,由于编译错误,我无法调用 range (*ea)
。
最佳答案
看起来这两种类型都具有基础类型 map[string]something
,其中“something”具有具体类型 amf0.NumberType
。您所做的每个操作都可以使用反射来模拟。
switch md.(type) {
case *amf0.EcmaArrayType, *amf0.ObjectType:
m := reflect.Indirect(reflect.ValueOf(md))
for _, key := range m.MapKeys() {
k, v := key.Interface(), m.MapIndex(key).Interface()
log.Printf("%v = %v\n", k, v)
}
if width == 0 {
w := m.MapIndex(reflect.ValueOf("width"))
width = uint16(w.Interface().(amf0.NumberType))
}
if height == 0 {
h := m.MapIndex(reflect.ValueOf("height"))
height = uint16(h.Interface().(amf0.NumberType))
}
}
然而,您在第一个示例中所做的事情并不少见。有时反射不会削减它。在这些情况下,我对您的类型转换有一些建议。而不是 switch md.(type)
做 switch ea := md.(type)
。这将允许您删除像 ea := md.(*amf0.EcmaArrayType)
这样的行。
DRY 代码更易于使用。它使更改更快并且更不容易出现错误。然而,当所有重复的代码都在一个地方(如类型转换)时,出现错误的可能性很小。进行更改仍然需要更长的时间,但它并不像整个项目中的重复代码那么糟糕。不要像担心其他重复代码那样担心大量重复的类型开关。
关于types - go 中的类型转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13332746/