Why is len
a function and not a method?
We debated this issue but decided implementing len
and friends as functions was fine in practice and didn't complicate questions about the interface (in the Go type sense) of basic types.
我们讨论了这个问题,但决定把len跟其他内置的作为函数实现,因为函数在实践中很好,并且不会使有关基本类型的接口(在 Go 类型意义上)的问题复杂化。
Why does Go not support overloading of methods and operators?
为什么 Go 不支持方法和运算符的重载?
Method dispatch is simplified if it doesn't need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
其他语言的经验告诉我们如果方法分派也不需要进行类型匹配,那么它就会被简化。使用具有相同名称但不同签名的多种方法有时是有用的,但在实践中也可能会造成混乱和脆弱。仅按名称匹配并要求类型一致是 Go 类型系统中的一个重大简化决策。
fragile
adj. 易碎的,脆的;虚弱的;
Regarding operator overloading, it seems more a convenience than an absolute requirement. Again, things are simpler without it.
关于运算符重载,它似乎更多的是一种方便,而不是绝对的要求。同样,如果没有它,事情会变得更简单。
Why doesn't Go have "implements" declarations?
为什么 Go 没有“implements”声明?
A Go type satisfies an interface by implementing the methods of that interface, nothing more. This property allows interfaces to be defined and used without needing to modify existing code. It enables a kind of structural typing that promotes separation of concerns and improves code re-use, and makes it easier to build on patterns that emerge as the code develops. The semantics of interfaces is one of the main reasons for Go's nimble, lightweight feel.
Go 类型通过实现接口的方法来满足接口,仅此而已。此属性允许定义和使用接口,而无需修改现有代码。它支持一种 结构类型,可以促进关注点分离并提高代码重用性,并且可以更轻松地构建随着代码开发而出现的模式。接口的语义是 Go 灵活、轻量级感觉的主要原因之一。
semantics
n. 语义学;词义学;
nimble
adj. 灵活的;敏捷的;(头脑)思路敏捷的,机智的;机敏的;
See the question on type inheritance for more detail.
有关更多详细信息, 请参阅有关类型继承的问题。
How can I guarantee my type satisfies an interface?
如何保证我的类型满足接口?
You can ask the compiler to check that the type T
implements the interface I
by attempting an assignment using the zero value for T
or pointer to T
, as appropriate:
您可以要求编译器通过尝试使用 T
零值 或 T
指针进行赋值,来检查类型T是否实现了接口I(视情况而定)
type T struct{}
var _ I = T{} // 验证 T 是否实现 I。
var _ I = (*T)(nil) // 验证 *T 是否实现 I。
If T
(or *T
, accordingly) doesn't implement I
, the mistake will be caught at compile time.
如果T(或者*T,相应地)没有实现 I,错误将在编译时被捕获。
If you wish the users of an interface to explicitly declare that they implement it, you can add a method with a descriptive name to the interface's method set. For example:
如果您希望接口的用户显式声明他们实现了该接口,则可以将具有描述性名称的方法添加到接口的方法集中。例如:
type Fooer interface {
Foo()
ImplementsFooer()
}
A type must then implement the ImplementsFooer
method to be a Fooer
, clearly documenting the fact and announcing it in go doc's output.
然后,类型必须将ImplementsFooer
方法实现为 a Fooer
,清楚地记录事实并在 go doc的输出中宣布它。
type Bar struct{}
func (b Bar) ImplementsFooer() {}
func (b Bar) Foo() {}
Most code doesn't make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they're necessary to resolve ambiguities among similar interfaces.
大多数代码不使用此类约束,因为它们限制了界面思想的实用性。但有时,它们对于解决类似接口之间的歧义是必要的。
Why doesn't type T satisfy the Equal interface?
为什么类型T不满足Equal接口?
Consider this simple interface to represent an object that can compare itself with another value:
考虑这个简单的接口来表示一个可以将自身与另一个值进行比较的对象:
type Equaler interface {
Equal(Equaler) bool
}
and this type, T
:
和这种类型T:
type T int
func (t T) Equal(u T) bool { return t == u } // does not satisfy Equaler
Unlike the analogous situation in some polymorphic type systems, T
does not implement Equaler
. The argument type of T.Equal
is T
, not literally the required type Equaler
.
与某些多态类型系统中的类似情况不同, T不实现Equaler. 的参数类型T.Equal是T,而不是字面意义上的所需类型Equaler。
polymorphic
adj. 多形的,多态的,多形态的;多晶形;
In Go, the type system does not promote the argument of Equal
; that is the programmer's responsibility, as illustrated by the type T2
, which does implement Equaler
:
Equal在 Go 中,类型系统不提倡; 的参数 。这是程序员的责任,如类型所示T2,它确实实现了 Equaler:
type T2 int
func (t T2) Equal(u Equaler) bool { return t == u.(T2) } // satisfies Equaler
Even this isn't like other type systems, though, because in Go any type that satisfies Equaler
could be passed as the argument to T2.Equal
, and at run time we must check that the argument is of type T2
. Some languages arrange to make that guarantee at compile time.
但即便如此,这也不像其他类型系统,因为在 Go 中,任何 满足的类型都Equaler可以作为参数传递给T2.Equal,并且在运行时我们必须检查参数的类型是否为T2。有些语言安排在编译时做出这种保证。
A related example goes the other way:
一个相关的例子则相反:
type Opener interface {
Open() Reader
}
func (t T3) Open() *os.File
In Go, T3
does not satisfy Opener
, although it might in another language.
在 Go 中,T3不满足Opener,尽管在另一种语言中可能满足 。
While it is true that Go's type system does less for the programmer in such cases, the lack of subtyping makes the rules about interface satisfaction very easy to state: are the function's names and signatures exactly those of the interface? Go's rule is also easy to implement efficiently. We feel these benefits offset the lack of automatic type promotion. Should Go one day adopt some form of polymorphic typing, we expect there would be a way to express the idea of these examples and also have them be statically checked.
虽然在这种情况下,Go 的类型系统确实为程序员做的事情较少,但缺乏子类型使得关于接口满足的规则非常容易声明:函数的名称和签名是否与接口的名称和签名完全相同?Go 的规则也很容易高效地实现。我们认为这些好处弥补了自动类型升级的不足。如果有一天 Go 采用某种形式的多态类型,我们期望有一种方法来表达这些示例的想法,并让它们进行静态检查。