【问题标题】:Golang: Type assign with another structGolang:使用另一个结构键入分配
【发布时间】:2016-10-25 19:29:51
【问题描述】:

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

【问题讨论】:

    标签: go methods struct embedding


    【解决方案1】:

    这个:

    type Form Rectangle
    

    创建一个名为Form 类型,将Rectangle 作为其基础 类型。

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

    但方法绑定到特定类型。当您创建一个新类型 (Form) 时,该新类型将没有其底层类型的任何方法,因此您不能调用 c.SomethingElse(),因为 SomethingElse()Rectangle 类型的方法。

    c.Circle.Something() 有效,因为c.CircleCircle 类型的字段,而Something()Circle 类型的方法。

    如果要调用Rectangle.SomethingElse() 方法,则需要Rectangle 类型的值(接收器类型为Rectangle)。由于Form 的底层类型是Rectangle,因此您可以使用简单类型conversionForm 类型的值中简单地获取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的内存表示,所以它非常安全高效 em>。

    如果您希望新类型具有“旧”类型的方法,请使用嵌入。请参阅 Ainar-G 的答案。实际上,您已经通过在Rectangle 中嵌入Circle 来做到这一点:Rectangle 类型有一个方法Something(),因为Something()Circle 的一个方法:

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

    【讨论】:

    • 感谢您的精彩解释!
    【解决方案2】:

    Go 中的一个简单规则。如果您想要类型的方法,请执行

    type A struct { B }
    

    如果你想要该类型的方法,那么

    type A B
    

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

    Go 让您可以获取相同的类型,但方法集为空。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 1970-01-01
        • 2013-10-17
        • 2022-01-02
        • 2023-04-04
        • 2016-02-08
        • 2011-01-19
        相关资源
        最近更新 更多