为了账号安全,请及时绑定邮箱和手机立即绑定

理解 Go 中的接口和模拟

理解 Go 中的接口和模拟

Go
慕莱坞森 2022-06-27 09:37:04
2·1我正在尝试为 AWS 服务 ( ECR ) 构建抽象。这是代码:type ECR struct {    Client ecriface.ECRAPI    Ctx    context.Context}// ECRCreate establishes aws session and creates a repo with provided inputfunc (e *ECR) ECRCreate(ecrInput *ecr.CreateRepositoryInput) {    result, err := e.Client.CreateRepositoryWithContext(e.Ctx, ecrInput)    if err != nil {        if aerr, ok := err.(awserr.Error); ok {            switch aerr.Code() {            case ecr.ErrCodeServerException:                log.Errorln(ecr.ErrCodeServerException, aerr.Error())            case ecr.ErrCodeInvalidParameterException:                log.Errorln(ecr.ErrCodeInvalidParameterException, aerr.Error())            case ecr.ErrCodeInvalidTagParameterException:                log.Errorln(ecr.ErrCodeInvalidTagParameterException, aerr.Error())            case ecr.ErrCodeTooManyTagsException:                log.Errorln(ecr.ErrCodeTooManyTagsException, aerr.Error())            case ecr.ErrCodeRepositoryAlreadyExistsException:                log.Errorln(ecr.ErrCodeRepositoryAlreadyExistsException, aerr.Error())            case ecr.ErrCodeLimitExceededException:                log.Errorln(ecr.ErrCodeLimitExceededException, aerr.Error())            case ecr.ErrCodeKmsException:                log.Errorln(ecr.ErrCodeKmsException, aerr.Error())            default:                log.Errorln(aerr.Error())            }        } else {            // Print the error, cast err to awserr.Error to get the Code and            // Message from an error.            log.Errorln(err.Error())        }        return    }    log.Infof("Result: %v", result)}要模拟 aws sdk 创建存储库调用: type mockECRClient struct {    ecriface.ECRAPI}这有效。但是,我对这里的界面和组合的使用有点困惑。ECRAPI 由 ecriface 包定义,我实现了接口的签名之一,并且仍然能够使用模拟客户端mockSvc。问题:这是如何运作的?这是模拟接口的惯用方式吗?ECRAPI接口的其他方法呢?那些是如何照顾的?那么我的理解是否正确,我们可以定义具有任意数量的方法签名的接口,将该接口嵌入到结构中,然后将结构传递到预期接口的任何位置。但这意味着,我跳过实现我的接口的其他签名?我想我在这里遗漏了一些重要的概念,请指教!
查看完整描述

1 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

简短的回答是:这是有效的,因为测试的函数只调用您明确定义的方法。如果它调用其他任何东西,它将失败。


这是如何发生的:


该mockECRClient结构嵌入了接口,因此它具有该接口的所有方法。但是,要调用任何这些方法,您必须将该接口设置为实现:


x:=mockECRClient{}

x.ECRAPI=<real implementation of ECRAPI>

Func对定义为 for的 x.Func() 的ECRAPI调用实际上会调用x.ECRAPI.Func(). 由于您没有设置 ECRAPI,因此x.ECRAPI上面是 nil,并且您调用的任何使用接收器的方法都会恐慌。


mockECRClient但是,您为:定义了一个方法CreateRepositoryWithContext。当你调用x.CreateRepositoryWithContext时,方法属于x和不属于x.ECRAPI,接收者将是x,所以它工作。


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 104 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信