理解 Go 中的接口和模拟

2·1我正在尝试为 AWS 服务 ( ECR ) 构建抽象。这是代码:


type ECR struct {

    Client ecriface.ECRAPI

    Ctx    context.Context

}


// ECRCreate establishes aws session and creates a repo with provided input

func (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接口的其他方法呢?那些是如何照顾的?

那么我的理解是否正确,我们可以定义具有任意数量的方法签名的接口,将该接口嵌入到结构中,然后将结构传递到预期接口的任何位置。但这意味着,我跳过实现我的接口的其他签名?


我想我在这里遗漏了一些重要的概念,请指教!


慕莱坞森
浏览 105回答 1
1回答

aluckdog

简短的回答是:这是有效的,因为测试的函数只调用您明确定义的方法。如果它调用其他任何东西,它将失败。这是如何发生的:该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,所以它工作。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go