gpt4 book ai didi

go - 结构和接口(interface)类型

转载 作者:行者123 更新时间:2023-12-01 22:31:31 25 4
gpt4 key购买 nike

有人可以解释一下(或者如果要解释一下至少要向我指出一些文档是一件很长的事情)为什么这段代码的行为如此。它有点长,但我想不出一个在不丢失太多信息的情况下缩短它的好方法。

让我感到困惑的是,我需要在每种类型的结构上都有“查找”方法才能将其识别为它的类型。仅在 baseTypeImp 上查找是否打印每个都是 baseTypeImp,如果我在 baseTypeImp 和 advancedBaseTypeImp 上有它,那么这两个是正确识别的,但不是最后一个类型。

PlaygroundLink

我的代码

package main

import (
"fmt"
"reflect"
)

type BaseType interface {
Name() string
Find(string) BaseType
Children() []BaseType
Options()
}

type baseTypeImp struct {
name string
children []BaseType
}

func (b baseTypeImp) Options() {
fmt.Println("Not implemented")
}

func (b baseTypeImp) Find(name string) BaseType {
if b.name == name {
return b
}

for _, c := range b.children {
if m := c.Find(name); m != nil {
return m
}
}
return nil
}

func (b baseTypeImp) Name() string {
return b.name
}
func (b baseTypeImp) Children() []BaseType {
return b.children
}

type AdvancedBaseType interface {
Value()
}

type advancedBaseTypeImp struct {
baseTypeImp
}

func (a advancedBaseTypeImp) Options() {
fmt.Println("Is implemented")
}

func (a advancedBaseTypeImp) Value() {
fmt.Println("Value called")
}

func (a advancedBaseTypeImp) Find(name string) BaseType {
if a.name == name {
return a
}

for _, c := range a.children {
if m := c.Find(name); m != nil {
return m
}
}
return nil
}

type reallyAdvancedBaseTypeImp advancedBaseTypeImp

func newThingy(name, variant string, children []BaseType) BaseType {
base := baseTypeImp{name: name, children: children}
switch variant {
case "advanced":
return advancedBaseTypeImp{baseTypeImp: base}
case "reallyAdvanced":
return reallyAdvancedBaseTypeImp{baseTypeImp: base}
}
return base
}

func whatType(b BaseType) {
if b == nil {
return
}
fooType := reflect.TypeOf(b)
fmt.Println(b.Name(), " is type ", fooType.Name())
b.Options()
}

func main() {
advanced := make([]BaseType, 0, 5)
for i := 0; i < 5; i++ {
advanced = append(advanced, newThingy(fmt.Sprintf("Advanced %d", i), "advanced", nil))
}
reallyAdvanced := make([]BaseType, 0, 2)
for i := 0; i < 2; i++ {
reallyAdvanced = append(reallyAdvanced, newThingy(fmt.Sprintf("ReallyAdvanced %d", i), "reallyAdvanced", advanced[i:i+3]))
}
basic := newThingy("Basic parent", "basic", reallyAdvanced)
whatType(basic.Find("Basic parent"))
for i := 0; i < 2; i++ {
whatType(basic.Find(fmt.Sprintf("Advanced %d", i)))
whatType(basic.Find(fmt.Sprintf("ReallyAdvanced %d", i)))
}
}

现在的输出是:
Basic parent  is type  baseTypeImp
Not implemented
Advanced 0 is type advancedBaseTypeImp
Is implemented
ReallyAdvanced 0 is type baseTypeImp
Not implemented
Advanced 1 is type advancedBaseTypeImp
Is implemented
ReallyAdvanced 1 is type baseTypeImp
Not implemented

我想要的是:
Basic parent  is type  baseTypeImp
Not implemented
Advanced 0 is type advancedBaseTypeImp
Is implemented
ReallyAdvanced 0 is type reallyAdvancedBaseTypeImp
Is implemented
Advanced 1 is type advancedBaseTypeImp
Is implemented
ReallyAdvanced 1 is type reallyAdvancedBaseTypeImp
Is implemented

有没有办法让这个工作而不必在每个级别上实现 Find?这有点违背了在顶层结构中使用通用方法的目的。当然,如果可能的话,请解释为什么它的行为方式。

最佳答案

当您将一个结构嵌入到另一个结构中时,外部结构会获取嵌入结构的方法。

type inner struct {
}

func (i inner) f() {}

type outer struct {
inner
}
...

x:=outer{}
x.f()

您可以将其视为语法糖:
type outer2 struct {
i inner
}

y.i.f()

当您嵌入 inner如果没有字段名,您只需删除 i在通话中。您仍然可以调用 x.inner.f()在第一个例子中。

当您重新定义一个类型时,它不会获得为其基类型定义的方法。
type newtype inner
newtype没有 f()定义。但是,如果 inner还嵌入了其他结构(就像你做的那样),然后那些仍然嵌入到新类型中,所以定义了这些函数:
type deepest struct {}
func (deepest) deep() {}

type inner struct{}
func (inner) in() {}

type outer inner

以上,类型 outer没有功能 in ,但它有 deep .

所以当你调用 reallyAdvancedBaseTypeImp.Find() ,你真正在做的是 reallyAdvancedBaseTypeImp.baseTypeImp.Find() ,它适用于结构的那部分。这就是为什么你得到你得到的类型。

您正在尝试模拟方法覆盖。你真的不能那样做。以不同的方式阐述你的问题。

关于go - 结构和接口(interface)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61257608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com