草庐IT

go - GoLang 对由结构和嵌入式结构实现的接口(interface)的类型转换是如何工作的

coder 2024-07-05 原文

我最近发现一段代码在做一些我不理解的事情。

有多个结构具有相同的嵌入式结构和一个接口(interface),该接口(interface)定义返回指向每个结构的指针的方法。此接口(interface)由嵌入式结构实现,但仅“部分”由各个结构实现,因此,每个结构仅实现返回指向该结构的指针的方法。

为了更好的理解,这里有代表性的代码:

type BarStocks interface {
    GetVodka() *Vodka
    GetMartini() *Martini
    GetBourbon() *Bourbon
    GetNegroni() *Negroni
    GetManhattan() *Manhattan
}

type BaseAttributes struct {
    ID        uuid.UUID
    Quantity float64
    CreatedAt time.Time
    UpdatedAt time.Time
}

func (e *BaseAttributes) GetVodka() *Vodka {
    return nil
}

func (e *BaseAttributes) GetMartini() *Martini {
    return nil
}

func (e *BaseAttributes) GetBourbon() *Bourbon {
    return nil
}

func (e *BaseAttributes) GetNegroni() *Negroni {
    return nil
}

func (e *BaseAttributes) GetManhattan() *Manhattan {
    return nil
}

然后每个单独的结构只实现返回其指针的方法,例如:

type Vodka struct {
    BaseAttributes

    Label string
}

func (v *Vodka) GetVodka() *Vodka {
    return v
}

现在在代码中,此设置用于将单个结构作为指针类型转换为接口(interface),如下所示:

func someFunc() BarStocks {
    v := Vodka{}
    return &v
}

现在我对 Go 还不是很深入,所以无法理解指向结构的指针如何变成与接口(interface)相同的类型。

在此先感谢您对此的任何见解。

最佳答案

我会尽力回答您提出的问题。

documentation关于嵌入解释了您所看到的行为,

There's an important way in which embedding differs from subclassing. When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one.

这解释了 Vodka 结构,它嵌入了结构 BaseAttributes,它实现了 BarStocks 中的所有方法,能够满足接口(interface) 棒材。然而,这段摘录并没有解释我们如何有效地为我们的 Vodka 结构覆盖 GetVodka()

要理解这一点,我们需要阅读文档中的另一段摘录。

Embedding types introduces the problem of name conflicts but the rules to resolve them are simple. First, a field or method X hides any other item X in a more deeply nested part of the type.

这段摘录解释了如果 Vodka 实现了 GetVodka() 并嵌入了一个结构 (BaseAttributes),它也实现了 GetVodka() ,最外层的定义优先。

这些行为的组合解释了 Vodka 如何满足 BarStocks 接口(interface)并具有您在示例代码中看到的行为。

关于go - GoLang 对由结构和嵌入式结构实现的接口(interface)的类型转换是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49962698/

有关go - GoLang 对由结构和嵌入式结构实现的接口(interface)的类型转换是如何工作的的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  4. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  5. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  6. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  7. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  8. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  9. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  10. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

随机推荐