英文:
Golang microservice middleware allow any type but be strict on endpoint
问题
我是你的中文翻译助手,以下是你要翻译的内容:
对于我刚开始使用golang,我想做的是使我的日志中间件通用化,例如允许任何类型,并调用下一层的方法。
下面是loggingmiddleware包的代码,我希望能够接受任何类型并将其打印出来。
package loggingmiddleware
import (
"context"
"time"
gokitlogger "github.com/go-kit/kit/log"
)
type layer interface {
Run(context.Context, interface{}) (interface{}, error)
}
type LoggingMiddleware struct {
Logger gokitlogger.Logger
Layer layer
}
func (mw LoggingMiddleware) Run(ctx context.Context, i interface{}) (output interface{}, err error) {
defer func(begin time.Time) {
mw.Logger.Log(
"method", "name of method",
"input", i,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = mw.Layer.Run(ctx, i)
return
}
然而,当调用下一个方法时,我希望能够严格控制类型,如果需要是字符串,我希望将类型设置为字符串,而不是interface{}
。
在我的示例中,我希望确保只使用float64类型作为参数。
type mathServiceInterface interface {
Run(context.Context, float64) (float64, error)
}
type mathService struct{}
func (mathService) Run(_ context.Context, f float64) (float64, error) {
return f * f, nil
}
然而,使用当前的实现,我得到了以下错误...
# github.com/jakelacey2012/blankit/blankit-ms/sqaure
./main.go:92: cannot use ms (type mathServiceInterface) as type loggingmiddleware.layer in field value:
mathServiceInterface does not implement loggingmiddleware.layer (wrong type for Run method)
have Run(context.Context, float64) (float64, error)
want Run(context.Context, interface {}) (interface {}, error)
./main.go:92: cannot use loggingmiddleware.LoggingMiddleware literal (type loggingmiddleware.LoggingMiddleware) as type mathServiceInterface in assignment:
loggingmiddleware.LoggingMiddleware does not implement mathServiceInterface (wrong type for Run method)
have Run(context.Context, interface {}) (interface {}, error)
want Run(context.Context, float64) (float64, error)
我理解这个错误,但我不知道我的实现是否过于复杂,因为我不了解go语言。
希望我的表达有意义,我不确定如何给这个问题命名,所以请随意编辑。
如果你需要更多的代码来更好地解释,请告诉我。
英文:
New to golang but what I'm trying to do is make my logging middleware generic e.g. allow any type and then call the method for the next layer.
So below us the loggingmiddleware package, where I want to be able to accept any type and print it out.
package loggingmiddleware
import (
"context"
"time"
gokitlogger "github.com/go-kit/kit/log"
)
type layer interface {
Run(context.Context, interface{}) (interface{}, error)
}
type LoggingMiddleware struct {
Logger gokitlogger.Logger
Layer layer
}
func (mw LoggingMiddleware) Run(ctx context.Context, i interface{}) (output interface{}, err error) {
defer func(begin time.Time) {
mw.Logger.Log(
"method", "name of method",
"input", i,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = mw.Layer.Run(ctx, i)
return
}
However I want to be strict when calling the next method, if it needs to be string I want to set the type to be string rather than interface{}
In my example I want to make sure only a float64 type will be used as an argument
type mathServiceInterface interface {
Run(context.Context, float64) (float64, error)
}
type mathService struct{}
func (mathService) Run(_ context.Context, f float64) (float64, error) {
return f * f, nil
}
However with my current implementation I'm getting this error...
# github.com/jakelacey2012/blankit/blankit-ms/sqaure
./main.go:92: cannot use ms (type mathServiceInterface) as type loggingmiddleware.layer in field value:
mathServiceInterface does not implement loggingmiddleware.layer (wrong type for Run method)
have Run(context.Context, float64) (float64, error)
want Run(context.Context, interface {}) (interface {}, error)
./main.go:92: cannot use loggingmiddleware.LoggingMiddleware literal (type loggingmiddleware.LoggingMiddleware) as type mathServiceInterface in assignment:
loggingmiddleware.LoggingMiddleware does not implement mathServiceInterface (wrong type for Run method)
have Run(context.Context, interface {}) (interface {}, error)
want Run(context.Context, float64) (float64, error)
I understand the error, however I don't know whether my implementation is over complicating things because I don't know go.
I hope what I'm saying makes sense, I was unsure what to title this as so please feel free to edit it.
Also if you need more code to better explain please do let me know.
答案1
得分: 1
这些将由什么来调用?在某个时刻会有一个实际的消费者,而这个消费者将会(根据你的代码推测)使用一个接口(要么是layer
,要么是一个相同的接口)。如果有中间件,那么这个接口将会必然与中间件一样通用,也就是说,Run
方法的参数将会是一个interface{}
类型。因此,将下游的某个部分变得更具体(除了像你所看到的那样无法编译)是没有任何意义的:实际的消费者将看不到更具体的接口,它将看到的是Run(Context,interface{}) (interface{},error)
。
英文:
What's going to be calling these? At some point there is an actual consumer, and that consumer will (presumably, based on your code) be using an interface (either layer
or an identical interface). If there's middleware, that interface will necessarily be as generic as the middleware - i.e., taking a interface{}
as a parameter to Run
. So making something downstream more specific (besides not compiling as you've seen) doesn't make any sense: the actual consumer won't see the more-specific interface, it will see Run(Context,interface{}) (interface{},error)
.
答案2
得分: 1
错误消息已经说明了问题,对于一个类型来实现一个接口,它的方法必须完全匹配接口定义的方法。
不幸的是,这意味着你的系统无法按照设计工作。你要么需要使用interface{}
并在最终点断言为实际类型,要么你需要为每种类型使用单独的接口(和日志记录函数)。
英文:
The error message says it all, for a type to implement an interface its methods must exactly match the methods the interface defines.
Sadly, this means that your system won't work as designed. You will either need to use interface{}
and assert to the actual type at the end point, or you will need a separate interface (and logger function) for each type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论