Go Playground
package main import ( "fmt" ) type Circle struct{} func (c Circle) Something() { fmt.Println("something") } type Rectangle struct { Circle } func (a Rectangle) SomethingElse() { fmt.Println("SomethingElse") } type Form Rectangle func main() { c := Form{} c.Circle.Something() c.SomethingElse() }
我不明白为什么我可以从嵌入的Circle中调用Something,但不能从Form类型中的Rectangle调用Somethingelse.另外,我不明白当我声明一种其他类型的类型时会得到什么好处,比如Form中的类型.
type Form Rectangle
创建一个名为Form的新类型,将Rectangle作为其基础类型.
这意味着将为Form定义Rectangle(这是一个struct)的字段.
但是方法绑定到特定类型.当您创建新类型(Form)时,该新类型将不具有其基础类型的任何方法,因此您不能调用c.SomethingElse(),因为SomethingElse()是Rectangle类型的方法.
c.Circle.Something()有效,因为c.Circle是Circle类型的字段,而Something()是Circle类型的方法.
如果要调用Rectangle.SomethingElse()方法,则需要Rectangle类型的值(接收器类型为Rectangle).由于Form的基础类型是Rectangle,因此您可以使用简单类型conversion从Form类型的值中获取Rectangle类型的值:
Rectangle(c).SomethingElse() // This works
创建新类型的好处是,您可以为它创建/添加自己的方法.一个常见的例子是实现sort.Interface
接口.假设你有一些东西,例如[] Rectangle,或者您无法控制的某种类型的切片(因为它是另一个包的一部分 – 并且类型的方法只能在同一个包中定义).如果要对此切片进行排序,可以创建一个可以定义方法的新类型,sort.Interface的方法,例如:
type SortRectangle []Rectangle func (s SortRectangle) Len() int { return len(s) } func (s SortRectangle) Less(i,j int) bool { return s[i] <some-logic> s[j] } func (s SortRectangle) Swap(i,j int) { s[i],s[j] = s[j],s[i] }
sort.Sort()函数能够对实现sort.Interface的任何值进行排序. [] Rectangle没有,但我们刚刚创建了一个新类型的SortRectangle.如果我们有一个类型为[] Rectangle的值,我们可以将它转换为SortRectangle,因为前者是后者的基础类型,通过转换,我们有一个SortRectangle类型的值,可以传递给sort.Sort (),为了让它排序:
rs := []Rectangle{} // Sort rs: sort.Sort(SortRectangle(rs))
请注意,像上面的SortRectangle(rs)这样的转换只会更改运行时类型信息,它不会更改rs的内存表示,因此它非常安全和高效.
如果您希望新类型具有“旧”类型的方法,则使用嵌入.见Ainar-G的答案.事实上,你已经通过在Circle中嵌入Circle来做到这一点:Rectangle类型有一个Something()方法,因为Something()是Circle的一个方法:
Rectangle{}.Something() // Prints "something"