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 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)
  • ¥20 matlab yalmip kkt 双层优化问题