Golang:使用另一个结构类型分配

Golang: Type assign with another struct

所以我这里有这个例子: 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

创建一个名为 Formnew 类型,Rectangle 作为其 底层 类型。

这意味着 Rectangle(这是一个结构)的字段也将为 Form 定义。

但是方法绑定到特定类型。当您创建一个新类型 (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 因为前者是后者的基础类型,通过转换,我们有一个 [=41] 类型的值=] 可以传递给 sort.Sort(),以便对其进行排序:

rs := []Rectangle{}
// Sort rs:
sort.Sort(SortRectangle(rs))

注意像上面的转换SortRectangle(rs)只改变运行时类型信息,它不会改变rs的内存表示,所以它是完美的安全高效.

如果你想让新类型有"old"类型的方法,那就用embedding。请参阅 Ainar-G 的回答。事实上,您已经通过在 Rectangle 中嵌入 Circle 来做到这一点:类型 Rectangle 有一个方法 Something(),因为 Something() 是 [=25] 的一个方法=]:

Rectangle{}.Something()  // Prints "something"

type Form Rectangle的全部(也是唯一)理由是用不同方法定义一个类型。在您的示例中:没有方法。 c 是一个表单,没有方法,它存在的唯一理由是 而不是 具有 SomethingElse() 方法。

但是 Form 仍然嵌入了一个可以作为 c.Circle 访问的 Circle 并且它是一个 Circle 所以它显然有方法 Something().

一个简单的围棋规则。如果你想要类型的方法,做

type A struct { B }

如果您需要该类型的方法,

type A B

为什么我们需要第二种形式? 接口,例如。有时我们 想要一个值来满足接口,例如。其他时候你只需要类型而不是它的方法。

Go 使您有可能获得相同的类型,但方法集为空。