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
创建一个名为 Form
的 new 类型,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 使您有可能获得相同的类型,但方法集为空。
所以我这里有这个例子: 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
的 new 类型,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 使您有可能获得相同的类型,但方法集为空。