为什么Go语言的方法有奇怪的语法?

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

Why does the go language have a strange syntax for methods

问题

我无法很好地理解为什么Go开发者选择了像func (t Type) MethodName()这样的方法语法。尤其是在阅读了这篇文章并考虑到Go的极简主义之后,我无法接受这个事实。使用类似于func Type.MethodName()func Type::MethodName()的更简单的语法,通过隐式参数像thisself访问对象,是否已经足够了呢?或者我错过了当前语法所提供的任何优势吗?

英文:

I couldn't well understand why the go developers settled on a syntax like func (t Type) MethodName() for methods. I couldn't digest this fact especially after reading this and considering the fact that go is minimalistic. Wouldn't a simpler syntax like func Type.MethodName() or func Type::MethodName() been sufficient with the object accessed using an implicit argument like this or self. Or am I missing any advantages offered by the current syntax?

答案1

得分: 7

特定语法的目标非常特定于Go语言,并且不容易映射到其他语言的语法:

这种语法允许您定义一个**方法集**

  • 一个类型可以有与之关联的方法集。接口类型的方法集就是它的接口。
  • 任何其他类型T的方法集由所有使用接收器类型T声明的方法组成。
  • 相应指针类型*T的方法集是所有使用接收器*TT声明的方法的集合(也就是说,它还包含T的方法集)。

对于包含匿名字段的结构体,还有其他规则,详见结构体类型的部分。其他任何类型都有一个空的方法集。在方法集中,每个方法必须具有唯一的非空方法名。

类型的方法集决定了该类型实现的接口以及可以使用该类型的接收器调用的方法

这不仅仅是一个“优势”,而是Go的一个特性,可以轻松地为类型添加新的方法。

例如,请参阅“Go接口的一些示例是什么?”。

twotwotwo评论中补充道:

  • 显式接收器声明允许您做两件特定的事情:
    1. 决定某些方法将获得指针接收器,而其他方法(例如,小结构体上的非变异方法)则不会。
    2. 选择一个上下文特定的名称,而不是selfthis(例如,您可能有一个func (srv *Server)...)。在Go中,上下文特定的名称被认为是良好的风格。

请参阅Wiki CodeReviewComments

  • 方法接收器的名称应反映其身份,通常使用其类型的一个或两个字母缩写就足够了(例如,“c”或“cl”代表“Client”)。
  • 不要使用通用名称,如“me”、“this”或“self”,这些是面向对象语言中更强调方法而不是函数的标识符。该名称不需要像方法参数的名称那样具有描述性,因为其作用是显而易见的,不起文档作用。它可以非常简短,因为它将出现在类型的几乎每一行代码中;熟悉使得简洁成为可能。同时要保持一致性:如果您在一个方法中将接收器称为“c”,则在另一个方法中不要将其称为“cl”。
英文:

The goal of that particular syntax is very particular to the language Go and cannot easily be mapped to other language syntax:

This syntax allows you to define a method set

> A type may have a method set associated with it. The method set of an interface type is its interface.

> - The method set of any other type T consists of all methods declared with receiver type T.

  • The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

> Further rules apply to structs containing anonymous fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.

> The method set of a type determines the interfaces that the type implements and the methods that can be called using a receiver of that type.

It isn't so much an "advantage" than it is a Go feature allowing to easily extend a type with new methods.

See for instance "What are some examples of Go interfaces?".


twotwotwo adds in the comments:

> There are two particular things that an explicit receiver declaration lets you do:

> 1. decide that some methods will get pointer receivers and others (e.g., non-mutating methods on small structs) don't, and
2. choose a context-specific name instead of 'self' or 'this' (e.g., you might have a func (srv *Server)...).
Context-specific names are considered good style in Go


See Wiki CodeReviewComments

> The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client").

> Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions.
The name need not be as descriptive as a that of a method argument, as its role is obvious and serves no documentary purpose. It can be very short as it will appear on almost every line of every method of the type; familiarity admits brevity.
Be consistent, too: if you call the receiver "c" in one method, don't call it "cl" in another.

huangapple
  • 本文由 发表于 2014年7月20日 13:08:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/24847582.html
匿名

发表评论

匿名网友

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

确定