【问题标题】:Interface naming convention Golang接口命名约定 Golang
【发布时间】:2016-12-15 00:15:39
【问题描述】:

我将发布我的代码:

/*
*  Role will ALWAYS reserve the session key "role".
 */
package goserver

const (
    ROLE_KEY string = "role"
)

type Role string

//if index is higher or equal than role, will pass
type RolesHierarchy []Role

func (r Role) String() string {
    return string(r)
}

func NewRole(session ServerSession) Role {
    return session.GetValue(ROLE_KEY).(Role)
}

func (this Role) IsRole(role Role, hierarchy RolesHierarchy) bool {
    if role == this {
        return true
    }
    if len(hierarchy) == 0 {
        return false
    }
    var thisI int = 0
    var roleI int = 0
    //Duped roles in hierarchy are verified in verifyConfig during parse
    for i, r := range hierarchy {
        if this == r {
            thisI = i
        }
        if role == r {
            roleI = i
        }
    }
    //TODO I can probably condense what follows into one if
    if thisI == 0 && roleI == 0 {
        return false
    }
    return thisI >= roleI
}

func (this *Role) AssumeRole(session ServerSession, role Role) {
    session.SetValue(ROLE_KEY, role)
    *this = role
}

需要注意的是,ServerSession也是一个接口,调用“ServerSessioner”对我来说感觉很奇怪。

我正在玩弄用 IsRole() 和 AssumeRole() 创建接口的想法,但是“Roler”似乎很不稳定。我突然意识到,除了标准的“er”后缀之外,我真的不知道或曾经遇到过接口的命名约定。我似乎确实记得 VS C++ 的约定是在所有内容前面加上一个“I”。这是“惯用语”吗?

有什么建议吗?

【问题讨论】:

  • 我会称它为RoleSupport,但接触English.SE 确实是一项有趣的尝试。请考虑不要使用this 来命名方法接收者:这是不习惯的 Go 语言。 One example 讨论这些问题。
  • 不是单个字母,而是有意义的缩写——单个字母可以用于短函数(包括你的)。 “任何其他语言”肯定是夸大其词。好吧,出于某种原因,这对我来说不是问题:不同的语言只是感觉不同。新手程序员确实努力成为一招一式的狗,试图将他们学到的技能带到他们面临的任何新语言中(我自己肯定去过那里),但理解语言背后的哲学并坚持下去总是更好。跨度>
  • 至少这降低了下一个程序员处理你的代码的 WTF 因素。 ;-)
  • WTF 因素,“this”或“self”在我“知道”的至少六种语言中是“惯用的”

标签: go interface naming-conventions naming


【解决方案1】:

在 golang 中,按照惯例,一个方法的接口名称是 表示行为者的名词。例如,

the `Read` method implements the `Reader` interface, and
the `Generate` method implements the `Generator` interface.

最好明确约定的细节,不管它们是什么。当接口只需要一个函数或一组非常特定的函数时,这很好

有一种做法是使用I前缀作为函数的最小公分母,在这种情况下IRole将是一个更好的接口名称,因为接口定义了两个必须由所有代表@的类型满足的函数987654325@

【讨论】:

  • IsRoler 和 AssumeRoler -> IsserAssumer?大声笑,这在英语堆栈交换中可能会更好......
  • @Dale talks.golang.org/2014/names.slide#14 => 有时结果不是正确的英文,但我们还是这样做了:
  • @SarathSadasivanPillai.. 让我试着理解...如果我在这个上下文中引入一个结构(即与方法相关联的数据结构),我宁愿说“任何结构实现'Read' 方法变成了 Reader”,这有意义吗?让我在这里添加另一个快速问题:用作读取源的结构的名称是什么? “Sourcer”??,(我知道它在 Java 中是“可读的”!)
  • @Victor 接口名称取决于它实现的功能
  • @SarathSadasivanPillai,我明白了。我的想法是,出于某种原因,我基于 OO 的思想(在 JAVA 多年之后)仍然让我说接口描述了(同类)对象的行为,而 go 中的接口也描述了对象的行为。两种方式都是用一个对象来描述一个方法(一个或多个),我们同意吗?猜猜在 JAVA 中,您正在寻找一个描述客户端可以对对象执行的操作(对象可以“告诉”执行的操作)的 单词,而在 GOLANG 中,该单词仅与对象可以做。这让我想到了 Sourcer/Readable 的问题。
【解决方案2】:

我明白了,原来我可以使用“er”约定。

/*
*  Role will ALWAYS reserve the session key "role".
 */
package goserver

const (
    ROLE_KEY string = "role"
)

type Role string

//if index is higher or equal than role, will pass
type RolesHierarchy []Role

type RoleChecker interface {
    IsRole(Role, RolesHierarchy) bool
}

type RoleAssumer interface {
    AssumeRole(ServerSession, Role)
}

type RoleCheckerAssumer interface {
    RoleChecker
    RoleAssumer
}

func (r Role) String() string {
    return string(r)
}

func NewRole(session ServerSession) Role {
    return session.GetValue(ROLE_KEY).(Role)
}

func (this Role) IsRole(role Role, hierarchy RolesHierarchy) bool {
    if role == this {
        return true
    }
    if len(hierarchy) == 0 {
        return false
    }
    var thisI int = 0
    var roleI int = 0
    //Duped roles in hierarchy are verified in verifyConfig during parse
    for i, r := range hierarchy {
        if this == r {
            thisI = i
        }
        if role == r {
            roleI = i
        }
    }
    //TODO I can probably condense what follows into one if
    if thisI == 0 && roleI == 0 {
        return false
    }
    return thisI >= roleI
}

func (this *Role) AssumeRole(session ServerSession, role Role) {
   session.SetValue(ROLE_KEY, role)
   *this = role
}

感谢 Sarathsp 让我正确地思考这个问题。

【讨论】:

    【解决方案3】:

    在您的情况下,我只想将它们命名为 RoleCheckerRoleAssumer,即“合并”的 RoleCheckerAssumer。或者,如果您使用单一界面,则可能是 RoleHelperRoleChecker

    ServerSession 也可以,甚至只是Session(尤其是在没有“客户端”会话的情况下)。另一方面,ServerSessioner 不好,Session 不是动词,也不是接口的方法。


    关于约定的帖子很多。

    Effective Go: Interface names:

    按照惯例,单方法接口由方法名称加上 -er 后缀或类似修饰来命名以构造代理名词:ReaderWriterFormatterCloseNotifier 等。

    这样的名称有很多,尊重它们以及它们捕获的函数名称是有成效的。 ReadWriteCloseFlushString 等具有规范的签名和含义。为避免混淆,除非它具有相同的签名和含义,否则不要为您的方法提供这些名称之一。相反,如果您的类型实现了与知名类型上的方法具有相同含义的方法,请为其赋予相同的名称和签名;调用你的字符串转换器方法String 而不是ToString

    Interface Types @ What's in a name? - Talks at golang.org

    只指定一种方法的接口通常只是那个附加了“er”的函数名。

    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    

    有时结果不是正确的英语,但我们还是这样做了:

    type Execer interface {
        Exec(query string, args []Value) (Result, error)
    }
    

    有时我们会使用英语来使它更好听:

    type ByteReader interface {
        ReadByte() (c byte, err error)
    }
    

    当一个接口包含多个方法时,选择一个准确描述其用途的名称(例如:net.Conn、http.ResponseWriter、io.ReadWriter)。

    对于接收者名称,请勿使用 thisself 或类似名称。而是:

    Receivers @ What's in a name? - Talks at golang.org

    接收者是一种特殊的论点。

    按照惯例,它们是反映接收者类型的一两个字符, 因为它们通常出现在几乎每一行:

    func (b *Buffer) Read(p []byte) (n int, err error)
    
    func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
    
    func (r Rectangle) Size() Point
    

    接收者名称应该在一个类型的方法中保持一致。 (不要在一种方法中使用 r,而在另一种方法中使用 rdr。)

    Go Code Review Comments: Receiver Names:

    方法接收者的名字应该反映它的身份;通常,其类型的一两个字母缩写就足够了(例如“客户端”的“c”或“cl”)。不要使用诸如“me”、“this”或“self”之类的通用名称,这些是面向对象语言的典型标识符,它们更强调方法而不是函数。该名称不需要像方法参数那样具有描述性,因为它的作用是显而易见的并且没有任何记录目的。它可以很短,因为它几乎出现在该类型的每个方法的每一行;熟悉承认简洁。也要保持一致:如果您在一种方法中将接收器称为“c”,请不要在另一种方法中将其称为“cl”。

    【讨论】:

    • 单一方法接口“更容易”。 “Is()”让我失望了。我最终只使用了“checker()”。是的,抱歉,不会使用单个或两个字母标识符。我不在乎这里的惯用语是什么。我知道六种使用 this 或 self 的语言,为什么我要在这里打破约定,仅仅因为语言规范中的一些文档说我应该这样做?这或自我正是我的意思和我想要的。归根结底,我需要阅读我的代码,如果我在意大利面条中翻找一些单字母标识符,那有什么意义呢?
    • @Dale 你想做什么就做什么。没有人会强迫你做任何事情。只要您“单独”编码,它就不会打扰其他任何人。但是如果你想和其他人一起工作,或者其他人必须使用你的代码,你需要说一种“通用”的语言。将thisself作为方法接收者:In Go is naming the receiver variable 'self' misleading or good practise?
    • 谢谢。我不想争论。我确实计划开源这个堆。也许反馈会迫使我重新考虑我的决定。我仍然不相信设计师在这里的决定。话虽如此,我在 Go 中看到的几乎所有其他内容都非常令人印象深刻。
    猜你喜欢
    • 2010-10-15
    • 2014-12-07
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多