亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用指針接收器方法創建包裝現有類型的接口

使用指針接收器方法創建包裝現有類型的接口

Go
智慧大石 2023-06-26 16:40:25
我需要測試一個使用 Google Cloud Pubsub 的應用程序,因此必須包裝其類型pubsub.Client并pubsub.Subscriber用于測試目的。然而,盡管進行了多次嘗試,我還是無法獲得可編譯的接口。我試圖包裝的方法的定義是:func (s *Subscription) Receive(    ctx context.Context, f func(context.Context, *Message)) errorfunc (c *Client) Subscription(id string) *Subscription這是當前的代碼。界面Receiver(包裝器Subscriber)似乎可以工作,但我懷疑它可能需要更改才能修復SubscriptionMaker,所以我將兩者都包括在內。注意:我已經嘗試了幾種引用和取消引用指針的變體,所以請不要告訴我更改它,除非您解釋了為什么建議的配置是正確的或者您親自驗證了它的編譯。import (    "context"    "cloud.google.com/go/pubsub")type Receiver interface {    Receive(context.Context, func(ctx context.Context, msg *pubsub.Message)) (err error)}// Pubsub subscriptions implement Receivervar _ Receiver = &pubsub.Subscription{}type SubscriptionMaker interface {    Subscription(name string) (s Receiver)}// Pubsub clients implement SubscriptionMakervar _ SubscriptionMaker = pubsub.Client{}當前錯誤消息:common_types.go:21:5: cannot use "cloud.google.com/go/pubsub".Client literal (type "cloud.google.com/go/pubsub".Client) as type SubscriptionMaker in assignment:    "cloud.google.com/go/pubsub".Client does not implement SubscriptionMaker (wrong type for Subscription method)        have Subscription(string) *"cloud.google.com/go/pubsub".Subscription        want Subscription(string) Receiver
查看完整描述

2 回答

?
catspeake

TA貢獻1111條經驗 獲得超0個贊

首先,對于大多數用途,使用ptest包可能是測試 pubsub 的更簡單的方法。但是當然,您的具體問題可以適用于任何庫,并且下面的方法對很多事情都有用,而不僅僅是模擬pubsub。


使用接口來模擬這樣的庫的更廣泛目標是可行的。但是,當您希望模擬的庫返回您無法模擬的具體類型(可能是由于未報告的字段)時,情況會很復雜。所采取的方法比通常值得的要復雜得多,因為可能有更簡單的方法來測試代碼。

但是,如果您打算這樣做,則必須采取的方法是不要將整個包包裝在接口中,而不僅僅是您希望模擬的特定方法。

您還需要包裝您希望模擬的任何類型,這些類型也由您的接口返回或接受。這通常意味著您還需要修改生產代碼(而不僅僅是測試代碼),因此這有時可能會破壞現有代碼庫的交易。

我以前通常這樣做的地方是在模擬標準庫的 sql 驅動程序之類的東西時,但這里可以應用相同的方法。本質上,您需要為您的pubsub庫創建一個包裝器包,甚至可以在生產代碼中使用它。同樣,這可能會對現有代碼庫造成很大的干擾,但只是為了說明目的。使用您定義的接口:

package mypubsub


import "cloud.google.com/go/pubsub"


type Receiver interface {

? ? Recieve(context.Context, func(context.Context, *pubsub.Message) error)

}


type SubscriptionMaker interface {

? ? Subscription(string) Receiver

}

然后,您可以包裝默認實現,以便在生產代碼中使用:


// defaultClient wraps the default pubsub Client functionality.

type defaultClient struct {

? ? *pubsub.Client

}


func (d defaultImplementation) Subscription(name string) Receiver {

? ? return d.Client.Subscription()

}

當然,您需要擴展此包以包裝pubsub您正在使用的大部分或全部包。這可能有點令人畏懼。


但是一旦完成此操作,就可以mypubsub在代碼中的任何地方使用您的包,而不是直接依賴于該pubsub包。現在,您可以在需要測試的任何地方輕松更換模擬實現。


查看完整回答
反對 回復 2023-06-26
?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

這是不可能的。

在接口上定義方法的類型簽名時,它必須完全匹配。func (c *Client) Subscription(id string) *Subscription返回 a *Subscription,并且 a*Subscription是有效的Receiver,但它不算符合接口方法Subscription(string) Receiver。Go 需要函數簽名的精確匹配,而不是通常用于接口的鴨子類型風格。


查看完整回答
反對 回復 2023-06-26
  • 2 回答
  • 0 關注
  • 184 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號