如何在Golang中实现来自不同包的接口?

huangapple go评论85阅读模式
英文:

How to implement interface from a different package in golang?

问题

我是你的中文翻译助手,以下是翻译好的内容:

我是Go语言的初学者,正在尝试使用接口。我希望将接口放在一个单独的包中,这样我就可以在其他各种包中使用它来实现,并且可以将其提供给其他团队(.a文件),以便他们可以实现自定义插件。请看下面的示例,了解我想要实现的目标。

--- 文件夹结构 ---
gitlab.com/myproject/
interfaces/
shaper.go
shapes/
rectangle.go
circle.go

---- shaper.go ----
package interfaces

type Shaper interface{

Area() int

}

我如何确保rectangle.go实现了shaper接口?
我了解到Go语言会隐式地实现接口,这是否意味着rectangle.go会自动实现shaper.go,即使它位于不同的包中?

我尝试了下面的方式,但是当我运行gofmt工具时,它会删除import语句,因为它没有被使用。

--- rectangle.go ---
package shapes

import "gitlab.com/myproject/interfaces"

type rectangle struct{

length int
width int
}

func (r rectangle) Area() int {
return r.length * r.width
}

提前致谢。

英文:

I am beginner in golang and was trying interfaces. I want to keep interfaces in a separate packages so that I can use it to implement this in various other packages, also provide it to other teams (.a file) so that they can implement custom plugins. Please see example below on what I would like to achieve.

--- Folder structure ---
gitlab.com/myproject/
                  interfaces/
                            shaper.go
                  shapes/
                        rectangle.go
                        circle.go
 
---- shaper.go ---
package interfaces
 
type Shaper interface{
  
    Area() int
 
}

How do I ensure that the rectangle.go implements shaper interface?
I understand that go implements interfaces implicitly, does this mean rectangle.go automatically implements shaper.go even though it is in a different package?

I tried it like below, but when I run gofmt tool, it removes the import because it is unused.

--- rectangle.go ---
package shapes
 
import "gitlab.com/myproject/interfaces"
 
type rectangle struct{
 
  length int
  width int
}
 
func (r rectangle) Area() int {
 return r.length * r.width
}

Thanks in advance.

答案1

得分: 27

在Go语言维基百科中有一个关于接口的优秀部分:

Go语言中的接口通常属于使用该接口类型值的包,而不是实现这些值的包。实现接口的包应该返回具体的(通常是指针或结构体)类型:这样,可以在不需要进行大量重构的情况下向实现中添加新的方法。

这样做的好处是减少了包之间的耦合(不强制任何人为了接口而导入你的包),并且通常会导致更小的接口(允许人们只使用你构建的接口的子集)。

如果你是Go语言的新手,我强烈推荐阅读我提供的“Go代码审查评论”维基文章,如果你有更多时间,还可以阅读“Effective Go”。祝你编程愉快!

英文:

There is an excellent section in the go wiki about interfaces:

> Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values. The implementing package should return concrete (usually pointer or struct) types: that way, new methods can be added to implementations without requiring extensive refactoring.

This also has the advantage that it reduces coupling between packages (by not forcing anybody to import your package just for the interface) and it generally leads to smaller interfaces (by allowing people to consume only a subset of the interface that you would have built).

If you are new to go I highly recommend reading the "Go Code Review Comments" wiki article I linked and if you have some more time also Effective Go. Happy hacking!

答案2

得分: 1

假设你有一个使用Shaper的函数。你可以使用一个rectangle来测试这个函数,并通过这样做来确保实现正确:

func DoStuff(s Shaper) {
    s.Area()
}

func TestDoStuff(t *testing.T) {
    var s Shaper = rectangle{length: 5, width: 3}
    DoStuff(s)
    // 断言
}

如果rectangle没有实现Shaper接口,你将会得到如下错误:

cannot use rectangle literal (type rectangle) as type Shaper in assignment:
rectangle does not implement Shaper (missing Area method)

Effective Go中有这样的描述:

Go中的接口提供了一种指定对象行为的方式:如果某个对象可以做到这一点,那么它就可以在这里使用。

英文:

Let's say you have a function that uses a Shaper. You can test the function with a rectangle, and by doing so ensuring the implementation:

func DoStuff(s Shaper) {
	s.Area()
}

func TestDoStuff(t *testing.T) {
	var s Shaper = rectangle{length: 5, width: 3}
	DoStuff(s)
    // assertion
}

If rectangle does not implement Shaper, you'll get an error like this:

cannot use rectangle literal (type rectangle) as type Shaper in assignment:
rectangle does not implement Shaper (missing Area method)

Effective Go:

Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here.

huangapple
  • 本文由 发表于 2017年6月4日 01:10:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/44346572.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定