声明一个带有返回值错误的函数参数。

huangapple go评论79阅读模式
英文:

Declare a function parameter with returning value error

问题

我正在编写一个可以包装任何方法的指标方法。类似于:

func DoAndMonitor(f func() error, simpleKey string) {
    metrics.IncrCounter("activity."+simpleKey+".cnt", 1)
    if err := f(); err != nil {
        metrics.IncrCounter("activity."+simpleKey+".fail", 1)
    } else {
        metrics.IncrCounter("activity."+simpleKey+".fail", 1)
    }
}

这对某些情况有效。但是使用起来并不容易,比如我有以下任意函数:

myMethod() (val1 string , val2 string , err error)
myMethod2() (val string , err error)
myMethod3() (err error)
myMethod4() (val int64,  err error)

当我使用myMethod()时,可能会写出类似以下的代码:

ret1, ret2, err := myMethod()
if err := nil {
    //log 
    return nil, err;
} else {
    //do something...
    return something, nil
}

但是当我使用DoAndMonitor时,我希望DoAndMonitor函数能够返回与myMethod相同的类型,例如:

ret1, ret2, err := DoAndMonitor(func(){
   return myMethod() 
},"mykey");// 这是我希望的,但现在我无法实现

if err := nil {
    //log 
    return nil, err;
} else {
    //do something...
    return something, nil
}

我该如何实现这个目标?

英文:

I am writing a method to do metrics that can wrap any method. Something like:

func DoAndMonitor(f func() error, simpleKey string) {
	metrics.IncrCounter("activity."+simpleKey+".cnt", 1)
	if err := f(); err != nil {
		metrics.IncrCounter("activity."+simpleKey+".fail", 1)
	} else {
		metrics.IncrCounter("activity."+simpleKey+".fail", 1)
	}
}

This works for some cases. But it is not easy to use, say I have any functions below,

myMethod() (val1 string , val2 string , err error)
myMethod()2 (val string , err error)
myMethod()3 ( err error)
myMethod()4 (val int64,  err error)

When I use myMethod(), I may write something like:

ret1, ret2, err := myMethod()
if err :=nil {
    //log 
    return nil, err;
} else {
    //do something...
    return something,nil
}

But when I use DoAndMonitor, I hope the DoAndMonitor function can return the same type as myMethod like :

ret1, ret2, err := DoAndMonitor(func(){
   return myMethod() 
},"mykey");// this is what i hope, but i can't do this now

if err :=nil {
    //log 
    return nil, err;
} else {
    //do something...
    return something,nil
}

How can I achieve this?

答案1

得分: 1

你可以通过使用类型参数并对同一个函数进行几个变体来实现最接近的效果。

func DoAndMonitor(f func() error, simpleKey string) { ... }
func DoAndMonitor1[T any](f func() (T, error), simpleKey string) T {
    x, err := f()
    if err != nil {
        metrics.IncrCounter("activity."+simpleKey+".fail", 1)
    } else {
        metrics.IncrCounter("activity."+simpleKey+".success", 1)
    }
    return x
}
// 其他变体...

然后你可以这样调用你的函数:

x := DoAndMonitor1[int](func() (int, error) { return 42, nil }, "foo")

这是一个快速的 Playground 链接,用于演示这个概念,但是使用 panic 替代了你的指标统计:https://go.dev/play/p/SMAhUCoIYcj

英文:

The closest you can get to this is by using type parameters and making a few variations of the same function.

func DoAndMonitor(f func() error, simpleKey string) { ... }
func DoAndMonitor1[T any](f func() (T, error), simpleKey string) T {
    x, err := f()
    if err != nil {
        metrics.IncrCounter("activity."+simpleKey+".fail", 1)
    } else {
        metrics.IncrCounter("activity."+simpleKey+".success", 1)
    }
    return x
}
// and so on...

You could then invoke your function like so:

x := DoAndMonitor1[int](func() (int, error) { return 42, nil }, "foo")

A quick playground link to demonstrate this, but with panics instead of your nice metrics. 声明一个带有返回值错误的函数参数。
https://go.dev/play/p/SMAhUCoIYcj

huangapple
  • 本文由 发表于 2022年4月1日 12:06:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/71701684.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定