如果我有一个requests
包,它用GetText
方法定义了一个TextExtractor
接口,GetText
方法返回Text
类型,那么实现必须 * 完全 * 满足TextExtractor
约定,并且它们被强制导入Text
类型。
我有两种可能的TextExtractor
实现--一种使用AWS Comprehend,另一种使用AWS Textract。
文件 aws_理解.go
package aws_comprehend
type AwsComprehend struct{}
func (a *AwsComprehend) GetText() *Text {
// do some stuff with aws comprehend...
return &Text{
Text: "text",
Language: "language",
}
}
type Text struct {
Text string
Language string
}
文件 * 请求.go*
package requests
import "fmt"
type TextExtractor interface {
GetText() *Text
}
type Text struct {
Text string
Language string
}
func HandleRequest(textExtractor TextExtractor) {
text := textExtractor.GetText()
fmt.Println(text)
}
文件 main.go
package main
import (
"aws_comprehend"
"requests"
)
func main() {
textExtractor := new(aws_comprehend.AwsComprehend)
requests.HandleRequest(textExtractor)
// this does not work:
// cannot use textExtractor (variable of type *aws_comprehend.AwsComprehend) as
// requests.TextExtractor value in argument to requests.HandleRequest:
// *aws_comprehend.AwsComprehend does not implement requests.TextExtractor
// (wrong type for method GetText)
// have GetText() *aws_comprehend.Text
// want GetText() *requests.Text
}
我理解为什么这行不通,因为Go语言不支持协变结果类型,但我的问题是,这种情况下的标准编码方式是什么?Go语言提供了隐式接口,这意味着隔离包非常容易:调用包定义了它所使用的接口,并且它被传递了实现这些接口的实现。这意味着**包根本不需要相互引用。但是如果一个包定义了一个接口,它返回的不仅仅是一个原语值,那么你必须故意共享这些值类型。如果GetText
返回一个string
,上面的代码就可以了。但是它返回一个struct
或其他接口的事实,意味着代码不能用这种方式编写。
我希望requests
包不知道任何关于aws_comprehend
包的信息,这是因为我有两个TextExtractor
接口的实现:一个使用AWS Comprehend,另一个使用AWS Textract。我 * 也 * 不希望包含一个“中间”包,该包具有requests
包和aws_comprehend
包都继承的接口。如果两个包必须继承相同的接口,那么它看起来就像是间接耦合到我,它破坏了隐式接口的想法。
我明白围棋很固执己见,那么解决这个问题的标准方法是什么呢?
1条答案
按热度按时间mtb9vblg1#
首先,你的文件布局是无效的。你不能有两个文件在同一个文件夹中,不同的包。所以下面是一个正确的布局。我也删除了所有的指针,因为他们不需要这个例子,只是分散注意力。
最后,我更新了该方法以返回正确的类型,以便代码实际编译:
aws_comprehend/aws_comprehend.go
:requests/request.go
:main.go
: