热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何避免在调用嵌入类型和嵌入类型之间具有不同行为的golang函数?

如何解决《如何避免在调用嵌入类型和嵌入类型之间具有不同行为的golang函数?》经验,为你挑选了1个好方法。

让我们说在第三方库中我们有一个接口和一个实现这个接口的结构.我们还假设有一个函数将ParentInterface作为参数,它对不同类型具有不同的行为.

type ParentInterface interface {
    SomeMethod()
}

type ParentStruct struct {
    ...
}

func SomeFunction(p ParentInterface) {
    switch x := p.Type {
    case ParentStruct:
        return 1
    }
    return 0
}

在我们的代码中,我们想要使用这个接口,但是使用我们的增强行为,所以我们将它嵌入到我们自己的结构中.编译器实际上允许我们ParentInterface直接在我的struct上调用函数:

type MyStruct struct {
    ParentInterface
}

parentStruct := ParentStruct{...}
myStruct := MyStruct{parentStruct}

parentStruct.SomeMethod()  // Compiler OK.
myStruct.SomeMethod()  // Compiler OK. Result is same. Great.

SomeFunction(parentStruct)  // Compiler OK. Result is 1.
SomeFunction(myStruct.ParentInterface)  // Compiler OK. Result is 1.
SomeFunction(myStruct)  // Compiler OK. Result is 0. (!)

最后一例不是问题吗?我不止一次遇到过这种错误.因为我愉快地使用MyStruct作为别名ParentInterface在我的代码(这就是为什么我在首位定义它),它是很难永远记住,我们不能称之为SomeFunctionMyStruct直接(编译器说,我们可以!).

那么避免这种错误的最佳做法是什么?或者它实际上是编译器的一个缺陷,它应该禁止使用,SomeFunction(myStruct)因为结果是不可信的?



1> icza..:

这里没有编译器错误,您的经验结果是预期的结果.

您的SomeFunction()函数明确声明它希望根据传递的接口值的动态类型执行不同的操作,这正是发生的事情.

我们首先介绍接口,因此我们不必关心实现接口的动态类型.界面为我们提供了对现有方法的保证,这些是你应该依赖的唯一东西,你应该只调用那些方法,而不是做一些类型切换或断言功夫.

当然这是理想的世界,但你应该尽可能地坚持下去.

即使在某些情况下,您无法将所有内容都放入接口中,但如果需要其他功能,则可以再次键入断言另一个接口而不是其中的具体类型.

一个典型的例子就是编写一个http.Handler将响应编写器作为接口的地方:http.ResponseWriter.它非常简约,但实际传递的类型可以做得更多.要访问"更多",您可以使用其他类型断言来获取额外的接口,例如http.Pusherhttp.Flusher.

在Go中,没有继承和多态.去赞成作文.将类型嵌入到另一个类型(struct)中时,嵌入类型的方法集将成为嵌入器类型的一部分.这意味着嵌入式实现的任何接口,嵌入器也将实现这些接口.并且调用那些实现的接口的方法会将调用"转发"到嵌入类型,也就是说,那些方法调用的接收器将是嵌入的值.除非您通过提供自己的实现,并将接收器类型作为嵌入器类型来"覆盖"这些方法.但即使在这种情况下,虚拟路由也不会发生.这意味着如果嵌入类型具有方法A()和调用的B()实现,如果您在嵌入器上提供自己的方法,则调用(嵌入类型)将不会调用的嵌入类型.A()B()B()A() B()

这不是要避免的东西(你无法避免),这是要了解的东西(要生活的东西).如果你知道它是如何工作的,你只需要考虑到这一点并用它来计算.

因为我很乐意在我的代码中使用它MyStruct作为别名ParentInterface(这就是为什么我首先定义它)

您不应该使用嵌入来创建别名,这是滥用嵌入.在您自己中嵌入类型不会是别名.检查具体类型的现有方法的实现将在您遇到时"失败"(意味着它们找不到与其预期的具体类型匹配).

除非您想"覆盖"某些方法或以这种方式实现某些接口,否则不应使用嵌入.只需使用原始类型.最简单,最干净.如果你需要别名,Go 1.9引入了类型别名功能,其语法是:

type NewType = ExistingType

在上述声明NewType与之相同之后ExistingType,它们将完全可互换(因此具有相同的方法集).但是要知道这并没有为语言添加任何新的"真实"功能,没有它们就可以使用类型别名来实现.它主要是为了支持更简单,渐进的代码重构.


推荐阅读
  • TICortexM3串口转以太网例程上层应用的基础是lwIP,版本是V1.3.2。对于lwIP,陌生的同学可以到网上查查,它是是瑞士的Adam编写的一个开源TCPIP协 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了[从头学数学]中第101节关于比例的相关问题的研究和修炼过程。主要内容包括[机器小伟]和[工程师阿伟]一起研究比例的相关问题,并给出了一个求比例的函数scale的实现。 ... [详细]
author-avatar
谢海武181_160
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有