Go 接口的同义结构字段和方法名称

Go 接口的同义结构字段和方法名称,go,struct,interface,Go,Struct,Interface,我正在构建一个类型结构,它表示网络上的一些设备。这些设备有很多类型,例如: type Foo struct { ... } type Bar struct { ... } type Spam struct { ... } 但它们都有几个公共字段,其中一个是IP。我想将设备定义为一个接口,这样我就可以在逻辑上将它们组合在一起 type Device interface { IP() string ... } type LogicalGrouping struct {

我正在构建一个类型结构,它表示网络上的一些设备。这些设备有很多类型,例如:

type Foo struct  { ... }
type Bar struct  { ... }
type Spam struct { ... }
但它们都有几个公共字段,其中一个是
IP
。我想将
设备
定义为一个接口,这样我就可以在逻辑上将它们组合在一起

type Device interface {
    IP() string
    ...
}

type LogicalGrouping struct {
    Devices []Device
    ...
}
但是我遇到了一个名字重叠的错误

func (f *Foo) IP() string { return f.IP }  // same method name as field name

我可以重命名字段或方法,也可以同时重命名两者,但这肯定是一个常见的用例——按结构的公共字段对结构进行分组?这里有惯用的解决方案吗?

一般的经验法则是接口定义行为,字段定义数据

这里的问题是,您正在使用一个接口来访问字段中的数据。就其本身而言,这不一定是件坏事。但是,您可能需要重新考虑如何构造代码,以免发生冲突

我想问的第一个问题是:

“如果
struct
定义了有权访问该字段的
IP()
方法,为什么需要导出该字段?”

您可以使结构字段未报告,即
ip
而不是
ip
,然后在使用
struct.ip
的地方,使用
struct.ip()

第二个问题是:

“如果您有结构,如
foo
bar
spam
,并且它们都共享公共字段,为什么不使用合成来消除这些共享字段的定义呢?”

这可能只有在您真正只关注结构内部的数据时才起作用,我通常主张在所有情况下都使用接口

如果您具有以下结构:

type Foo struct {
    IP string
    A string 
    B string
}

type Bar struct {
    IP string
    A string 
    B string
}

type Spam struct {
    IP string
    A string 
    B string
}
您可以使用一个新结构来表示它们的公共字段,并在其中匿名组合这些字段:

type Inner struct {
    IP string
    A string 
    B string
}

type Foo struct {
    Inner
}

type Bar struct {
    Inner
}

type Spam struct {
    Inner
}

在使用
struct.IP()。您可以访问<代码>结构> IP <代码>,即使<代码> IP <代码>在代码>内部< /代码>中定义。

您也可以考虑选择“<代码> IP 字段和<代码> GETP< <代码> SETIO/<代码>方法(或“代码> IP < /代码>和<代码> SETIP < /代码>相应地))-很清楚,简洁明了。

通常的解决方案是重命名结构字段,使其不被报告。字段和方法不能同名。只要字段和方法在语法上有效,那么它们的名称就完全取决于您。这是否回答了您的问题?一般来说,在go中,您不会创建
GetFoo()
方法,而是选择更简单的形式,即
Foo()
@扎克更新了我的答案。非常感谢。前一种方法(
foo.ip
unexported,使用
foo.ip()
进行数据访问)就是我最终使用的方法。我的大脑自然不会扭曲这种方式,因为我更容易地认为<代码> FUNC(f*fo)ip()字符串是接口上的一种方法,而不是结构上的一种方法——当然是胡说八道。