14 | 接口类型的合理运用
该思维导图由 AI 生成,仅供参考
前导内容:正确使用接口的基础知识
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了Go语言中接口类型的特性和运用。接口类型通过方法定义来构成方法集合,只要一个数据类型的方法集合中完全包含了一个接口的全部特征,那么它就是这个接口的实现类型。文章通过示例代码展示了接口变量的赋值和方法调用,引出了对于接口变量赋值后字段值的预期结果。此外,文章还详细解释了接口变量的动态值、动态类型和静态类型的概念,以及接口变量赋值时存储的数据结构。读者通过本文可以快速了解接口类型的特点和在Go语言中的合理运用。文章还介绍了接口之间的组合,强调了使用小接口和接口组合可以增加程序的灵活性和稳定性。文章最后提出了一个思考题,引发读者对接口方法调用的注意事项进行思考。通过本文,读者可以全面了解Go语言中接口类型的特性和运用,以及如何合理地使用接口组合来构建灵活的程序框架。
《Go 语言核心 36 讲》,新⼈⾸单¥59
全部留言(83)
- 最新
- 精选
- hiyanxu置顶老师,您好: 我在这篇文章中看到您说,给接口类型变量赋值时传递的都是副本,我测试了,确实是不会改变被赋值后的接口类型变量。 后面,我重新给Pet接口加上了SetName()方法,然后让*Dog类型实现了该Pet接口,然后声明并初始化了一个d,将d的地址&d赋值给Pet类型的接口变量: d := Dog{name: "little dog"} var pet Pet = &d 此时,我去修改了d的name字段: d.SetName("big dog") 运行后发现输出不仅d的name字段变为了“big dog”,同样pet接口变量也变成了“big dog”。 在此时我是不是可以说,传递给pet变量的同样是&d的一个指针副本,因为传递的是副本,所以无论是指针还是值,都可以说是浅复制;且由于传递的是指针(虽然是副本),但还是会对指向的底层变量做修改。 请问老师,我上面的推断是正确的吗? 另外我想说真的每篇文章都需要好好研读啊,看一篇得两个小时,里面好多干货,谢谢老师!
作者回复: 没错,虽然是副本,但却是指针的副本,SetName又是指针方法。所以综合起来这种修改就生效了。 另外这类副本都是浅表复制。也没错。
2018-12-19231 - 志鑫思考题,要看实现类型是值类型还是指针类型; var d2 Dog var p2 Pet = d2 if p2 != nil { fmt.Println("p2.Name()", p2.Name()) } var d3 *Dog var p3 Pet = d3 if p3 != nil { fmt.Println("p3.Name()", p3.Name()) //运行是报错,panic: value method main.Dog.Name called using nil *Dog pointer }
作者回复: 这主要是因为 Dog 和 *Dog 的零值是完全不同的,前者是 Dog{} ,而后者是 nil 。
2019-05-1035 - 俊杰老师您好,有个地方不理解,对象赋值给接口后,为什么判等操作返回的是true呢?比如上面的例子:pet = dog之后紧接着判断pet == dog,返回的是true,按上面的说法,赋值后不是应该被包装成了一个iface吗?这里的判等操作到底是依据什么来判断的呢?麻烦老师解释一下,谢谢~
作者回复: 你可以参照Go语言规范中的说明:https://golang.google.cn/ref/spec#Comparison_operators,请注意下面这句: A value x of non-interface type X and a value t of interface type T are comparable when values of type X are comparable and X implements T. They are equal if t's dynamic type is identical to X and t's dynamic value is equal to x.
2019-03-20413 - 吉他关于思考题,如果我们把一个值为nil的某个实现类型的变量赋给了接口变量,那么在这个接口变量上仍然可以调用该接口的方法吗? 可以的,不过方法内不能使用实现类型内的变量,并且方法接收者必须是指针类型
作者回复: 对的,对于指针方法来说是这样。
2019-05-25312 - lesserror郝林老师,这个专栏过去快三年了,里面的很多内容都对我受益很大。 但是好像没了老师的动态了,不知道郝林老师这几年都在从事什么类型的工作呢?
作者回复: 很高兴,谢谢关注哈:) 我还是依然在当“坐家”,依然没有全职工作。 (下面也算是我给自己的记录吧) 2019年,我出了一本新书《Julia编程基础》。Julia语言也是一门通用编程语言,不过更倾向于科学计算和数据科学。它的官方文档对初学者不友好,所以我就填补了一下空白,写了一本给小白看的Julia编程书。 2010年,我换了住址,也一直在找方向,做了一些尝试。但由于自身的执行力受限,这些尝试都没怎么出成果。年底的时候,我帮某个技术培训机构制定了一整套Go语言培训体系。 2021年,春节过后的一段时间,我为某大厂审核了Go语言编程规范。在这之后,我一直在规划和撰写一个新的教程,关于软件概要设计的。要是你有兴趣的话,可以关注我的微信公众号“迭代码”。我觉得如果能够写一本跟编程语言无关的软件设计书的话,应该可以帮助更多的人。:) 说到编程语言,我现在除了Go语言,还在重点关注Julia语言和Rust语言。我把Julia作为个人的数据挖掘语言,把Rust作为一种理解新编程技术和底层系统的帮手。 最后,其实我也挺想全职工作的,可惜条件还暂时不允许。不过,持续做一些我认为有意义的事,也算是一种积极的生活吧。
2021-07-31410 - 张硕_, ok := interface{}(dog).(Pet) 这个表达式是什么意思啊?
作者回复: 判断 dog 变量的值是不是 Pet 类型的,判断结果存于 ok 变量。
2020-03-3126 - Chaosdemo32.go line:32 var pet Pet = dog 是不是应该 var pet Pet = &dog 附:https://github.com/hyper0x/Golang_Puzzlers/blob/master/src/puzzlers/article14/q1/demo32.go
作者回复: 这是在示范“在原来的基本值上调用指针方法并修改其内部字段值”,然后展示“这样并不会改变接口值”。这是一个反例。需要大家运行之后思考的。 你有这样的思考,很好:)
2020-01-095 - 兔子高你好,请问分别在什么情况下使用值方法和什么情况下使用引用方法呢
作者回复: 需要改动值内部数据的时候必须使用指针方法。其他时候就要看接口实现、被嵌入要求等方面了。我觉得一般情况下用指针方法就好了。
2018-09-125 - saltedfish这有两个充分必要条件,一个是“两个方法的签名需要完全一致”,另一个是“两个方法的名称要一模一样”。显然,这比判断一个函数是否实现了某个函数类型要更加严格一些。 对于这里我有两个疑问: 1. 方法签名不就包括方法的名字吗? 2. 函数实现某个函数类型是什么意思?
作者回复: 1. 方法签名除了名字还有参数列表和结果列表啊。 2. 下面这行代码是在定义一个函数类型: type Check func(s string) bool 而下面这行代码是在定义一个函数(实现): func CheckLen(content string) bool { if len(content) >= 3 { return true } return false } 现在,我们可以说“函数 CheckLen 是函数类型 Check 的一个实例”。
2020-07-054 - Crush所有值为nil的变量a只要不是接口变量,a == nil是不是就成立?
作者回复: 更精确的说法是:除了接口类型以外的所有引用类型的值,只要它的实际值为nil,自然就等于nil。 多解释两句:对于这些类型,它们的值就是实际值。而接口类型的值与它们不同,会在实际值之外再包一层,正如文中所述。
2020-01-143