du21064 2017-08-03 06:29
浏览 49
已采纳

go中的泛型函数

I am trying to abstract the following pattern that seems to occur quite a lot, but the only way I can think of doing so is through a generic function:

func DoStuff () MyType {
    result, err := SomeProcess()  // returns MyType
    if err != nil {
        log.Fatal(err)
    }
    return result // or do something else with it
}

Here's my solution:

func FailOnError(value interface{}, err error) interface{} {
    if err != nil {
        log.Fatal(err)
    }
    return value
}

func DoStuff () MyType {
    return FailOnError(SomeProcess())
}

The problem is that I don't have compile-time type safety, and if I want to do anything further with the result I need to explicitly type cast it, e.g.

type MyType struct {
    value int
}

// Assuming a function with this signature
func GetItem() (MyType, error)

func Add () MyType {
    item := MyType(FailOnError(GetItem()))
}

This is ok, I guess, but rather inelegant. Also, it means manually enforcing types which is always somewhat fragile and a potential performance hit.

Is there a better, or more idiomatic way of doing this?

Edit: Since this seems to be a hated question, how about I use the following example instead:

func Identity(x interface{}) interface{} {
    return x
}

Usage would need to be:

x = int(Identity(1))
y = MyType(Identity(MyType{value}))

And there is nothing stopping me from doing

x = int(Identity(MyType{value}))

Identity is intentionally trivial, but need not necessarily be so. I could be, for example, and method designed to do some logging, or mutate an object and return it. Another situations I have is where I want to do some work on some types defined in various external libraries - they are similar enough that I can write a single function to handle all of them, but they don't share an interface.

  • 写回答

1条回答 默认 最新

  • dongzhi2014 2017-08-03 07:06
    关注

    Is there a better, or more idiomatic way of doing this?

    Yes: Handle the error. Log.Fatal is not error handling. If fataling is really the right thing: Encapsulate fataling only.

    Make fataling on error a function, not the calling and please stay away from interface{}:

    func abortOnError(err error) {
        if err == nil {return}
        log.Fatal(err)
    }
    
    func whatever() int {
        x, err := someOp()
        abortOnError(err)
        return x+2
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛