我试图抽象下面似乎发生很多的模式,但我能想到的唯一方法是通过一个通用函数:
func DoStuff () MyType {
result, err := SomeProcess() // returns MyType
if err != nil {
log.Fatal(err)
}
return result // or do something else with it
}
这是我的解决方案:
func FailOnError(value interface{}, err error) interface{} {
if err != nil {
log.Fatal(err)
}
return value
}
func DoStuff () MyType {
return FailOnError(SomeProcess())
}
问题是我没有编译时类型安全性,如果我想对结果做进一步的操作,我需要明确地输入它,例如。
type MyType struct {
value int
}
// Assuming a function with this signature
func GetItem() (MyType, error)
func Add () MyType {
item := MyType(FailOnError(GetItem()))
}
这是好的,我猜,但相当不优雅。此外,它意味着手动执行总是有些脆弱且潜在性能受损的类型。
是否有更好或更惯用的方法?
编辑:由于这似乎是一个讨厌的问题,我如何使用以下示例:
func Identity(x interface{}) interface{} {
return x
}
用法必须是:
x = int(Identity(1))
y = MyType(Identity(MyType{value}))
没有什么可以阻止我做
x = int(Identity(MyType{value}))
Identity
故意是微不足道的,但不一定如此。例如,我可以设计用于执行某些日志记录,或者改变对象并返回它。我的另一种情况是我想在各种外部库中定义的某些类型上做一些工作 - 它们足够相似,我可以编写一个函数来处理所有这些,但它们不共享一个接口。
答案 0 :(得分:1)
是否有更好或更惯用的方法?
是:处理错误。 Log.Fatal不是错误处理。如果致命真的是正确的事情:只封装致命的东西。
让错误导致函数致命,而不是调用,请远离interface{}
:
func abortOnError(err error) {
if err == nil {return}
log.Fatal(err)
}
func whatever() int {
x, err := someOp()
abortOnError(err)
return x+2
}