go interface 的坑

一、概述

 1 [root@node175 demo]# tree
 2 .
 3 ├── lib
 4 │   └── world.go
 5 ├── README
 6 └── server.go
 7
 8 1 directory, 3 files
 9
10 #server.go code
11 package main
12
13 import "fmt"
14 import "demo/lib"
15
16 type MyPrint struct {
17     name string
18 }
19
20 type Interface interface {
21     Print(string) error
22 }
23
24 func (this *MyPrint) Print(who string) error {
25     fmt.Printf("%s name is %s\n", who, this.name)
26     return nil
27 }
28
29 func MyselfPrint(name string) Interface {
30     return MyPrint{name: name}
31 }
32
33 func main() {
34     fmt.Println("Hi, " + lib.World())
35     MyInterface := MyselfPrint("bob")
36     fmt.Printf("MyInterface type: %T\n", MyInterface)
37     MyInterface.Print("my")
38 }

运行:

[root@node175 demo]# go run server.go
# command-line-arguments
./server.go:20: cannot use MyPrint literal (type MyPrint) as type Interface in return argument:
MyPrint does not implement Interface (Print method has pointer receiver)

  为了解决这个问题,首先得先了解一下Golang 中 方法的集合的概念,一个struct虽然可以通过值类型和引用类型两种方式定义方法,但是不通的对象类型对应了不同的方法集:

Values                    Methods Receivers
-----------------------------------------------
 T                        (t T)
*T                        (t T) and (t *T) 

  值类型的对象只有(t T) 结构的方法,虽然值类型的对象也可以调用(t *T) 方法,但这实际上是Golang编译器自动转化成了&t的形式来调用方法,并不是表明值类型的对象拥有该方法。

  换一个维度来看上面的表格可能更加直观:

1 Methods Receivers         Values
2 -----------------------------------------------
3 (t T)                     T and *T
4
5 (t *T)                    *T 

  这就意味着指针类型的receiver 方法实现接口时,只有指针类型的对象实现了该接口。

  对应上面的例子来说,只有&MyPrint实现了Interface接口,而MyPrint根本没有实现该接口。所以上面代码会报出这样的异常。

1 MyPrint method has pointer receiver
  解决这个问题也很容易,直接使用&MyPrint去代替MyPrint调用方法即可:
 1 package main
 2
 3 import "fmt"
 4 import "demo/lib"
 5
 6 type MyPrint struct {
 7     name string
 8 }
 9
10 type Interface interface {
11     Print(string) error
12 }
13
14 func (this *MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s\n", who, this.name)
16     return nil
17 }
18
19 func MyselfPrint(name string) Interface {
20     return &MyPrint{name: name}
21 }
22
23 func main() {
24     fmt.Println("Hi, " + lib.World())
25     MyInterface := MyselfPrint("bob")
26     fmt.Printf("MyInterface type: %T\n", MyInterface)
27     MyInterface.Print("my")
28 }

或者:

 1 package main
 2
 3 import "fmt"
 4 import "demo/lib"
 5
 6 type MyPrint struct {
 7     name string
 8 }
 9
10 type Interface interface {
11     Print(string) error
12 }
13
14 func (this MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s\n", who, this.name)
16     return nil
17 }
18
19 func MyselfPrint(name string) Interface {
20     return MyPrint{name: name}
21 }
22
23 func main() {
24     fmt.Println("Hi, " + lib.World())
25     MyInterface := MyselfPrint("bob")
26     fmt.Printf("MyInterface type: %T\n", MyInterface)
27     MyInterface.Print("my")
28 }
 再或者:
 1 package main
 2
 3 import "fmt"
 4 import "demo/lib"
 5
 6 type MyPrint struct {
 7     name string
 8 }
 9
10 type Interface interface {
11     Print(string) error
12 }
13
14 func (this MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s\n", who, this.name)
16     return nil
17 }
18
19 func MyselfPrint(name string) Interface {
20     return &MyPrint{name: name}
21 }
22
23 func main() {
24     fmt.Println("Hi, " + lib.World())
25     MyInterface := MyselfPrint("bob")
26     fmt.Printf("MyInterface type: %T\n", MyInterface)
27     MyInterface.Print("my")
28 }

 

时间: 2024-09-16 21:02:44

go interface 的坑的相关文章

如何设计一门编程语言(三) 什么是坑(面向对象和异常处理)

在所有的文字之前,我需要强调一下,我本人对structure typing持反对态度,所以就算文中的内容"看起来很像"go的interface,读者们也最好不要觉得我是在赞扬go的interface.我比较喜欢的是haskell和rust的那种手法.可惜rust跟go一样恨不得把所有的单词都缩成最短,结果代码写出来连可读性都没有了,单词都变成了符号.如果rust把那乱七八糟的指针设计和go的那种屎缩写一起干掉的话,我一定会很喜欢rust的.同理,COM这个东西设计得真是太他妈正确了,简

如何设计一门编程语言(二) 什么是坑(b)

我从来没有在别的语言的粉里面看见过这么容易展示人性丑陋一面的粉,就算是从十几年前开始的C++和C对喷,GC和非GC对喷,静态类型动态类型对喷的时候,甚至是云风出来喷C++黑得那么惊天动地的时候,都没有发生过这么脑残的事情.这种事情只发生在go语言的脑残粉的身上,这究竟代表什么呢?想学go语言的人最好小心一点了,学怎么用go没关系,go学成了因为受不了跳到别的语言去也没关系,就算是抖M很喜欢被折腾所以坚持用go也没关系,但是把自己学成了脑残粉,自己的心智发生不可逆转的变换,那就不好了. 当然,上一

Android Webview使用和遇到过的坑总结

本文讲的是Android Webview使用和遇到过的坑总结,WebView 用来显示网页的一个View,它使用WebKit渲染引擎显示web页面,可以加载在线的或者本地的html页面,WebView可以对页面进行一系列操作,如历史页面的向前.向后,放大和缩小,执行文本搜索,与JS交互等等; 在使用Webview时,请记得在AndroidManifest.xml文件中声明INTERNET权限: <uses-permission android:name="android.permissio

TinyRMI---RMI的封装、扩展及踩到的坑的解决

在Tiny的并行计算中,引用了远程方法调用工程,就是这里说的TinyRMI,当时在写测试用例的时候,只是在单机进行了测试,一切安好,但是Dawn在使用时,在多机进行试用,结果就出现了问题,最后花了不下一人周,才解决了Dawn发现的问题,最终解决了问题,也发现了RMI中的一些坑.可能有的人已经走过了,有的人如果没有碰到,也可能会掉同样的坑,因此把它成文,以飨读者,避免上同样的当. 此文的形成离不开Dawn的深入测试与分析,在此表示深深感谢! 功能需求 期望对Jdk中的Rmi进行一定的封装提供以下特

SQL SERVER 2012/2014 链接到 SQL SERVER 2000的各种坑

    本文总结一下SQL SERVER 2012/2014链接到SQL SERVER 2000的各种坑,都是在实际应用中遇到的疑难杂症.可能会有人说怎么还在用SQL SERVER 2000,为什么不升级呢? 每个公司都会有一两个几乎快被人遗忘的系统,接手维护这些系统的人可能都不知换了多少批了.它们的命运注定慢慢消亡.然而偏偏却又生命力顽强,总还有一些 人在使用着这些系统.所以就处在一种尴尬的境地: 升级吧,价值不大,可能再过一两年,这系统就要被其它系统替代了.而且项目经理也没有精力.人手耗费在

JAVA 入坑教程 | 章节一 基础概念

JAVA 章节一 基础概念 学JAVA,首先得知道JAVA是什么,JAVA能做什么事,JAVA有哪些概念和特性,首先我们从JAVA是什么开始入手带大家入坑: 前两篇内容我们提到了,JAVA的一些概念和特性,这篇文章我们来补足剩余的基本概念,当然,每篇文章的概念性东西会根据节奏走,每篇文章不会一次性带入太多的概念. OOP:Object Oriented Programming , 面向对象的程序设计 JAVA  三大特性 JAVA  其它的基础概念 一.OOP思想 首先我们来回顾下历史,OOP的

Android WebView使用的技巧与一些坑_Android

随着手机性能的提高,以及iOS和Android两个平台的普及,更多的App都会选择两个平台的App都进行开发,在有些时候,为了更加快速的开发,我们会采用hybird方式开发,这个时候我们需要使用webview并且自己进行一些配置.Android的webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了chrome,因此问题很多,这里分享一些我使用过程的一些技巧和遇到的坑.###webview配置### mWebview.getSettings().setJavaScri

Xcode 8新特性的使用和遇到的坑_IOS

目前还在用Xcode 7.3 一直没有更新,毕竟可怜了我弄的那么多插件...言归正传,自己从Xcode 8问世就一直在关注,今天偶然看到一篇文章总结的不错,随手转载过来顺便再次整理了一下,在此感谢原著作者! 原文如下: Xcode 8正式版在9月13日已经推送给开发者下载,我也在十一回来之后,就下载了新的Xcode.下载之后就出现了很多编译错误,之前的插件也不能用了,但是发现Xcode8把好多不错的插件功能整合到自身了,感觉这点也挺不错. 每个版本Xcode都会带来很多新特性,Xcode 8也不

iOS客户端NSDateFormatter那些坑

NSDateFormatter 会收到用户偏好设置的影响,所以有一些坑: 时区校验 有时候,我们需要把时间字符串转换为long类型的时间戳.比如下面例子: // 将"2016-02-06 00:00:00"转化为格林尼治标准的时间戳 NSString *timeStr = @"2016-02-06 00:00:00" NSDateFormatter *format = [[NSDateFormatter alloc] init]; [format setDateFo