• 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
    ", who, this.name)
    26     return nil
    27 }
    28 
    29 func NewMyPrint(name string) Interface {
    30     return MyPrint{name: name}
    31 }
    32 
    33 func main() {
    34     fmt.Println("Hi, " + lib.World())
    35     MyInterface := NewMyPrint("bob")
    36     fmt.Printf("MyInterface type: %T
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", MyInterface)
    27     MyInterface.Print("my")
    28 }
  • 相关阅读:
    71、salesforce的JSON方法
    70、saleforce的Json输出
    69、schema的相关方法
    javascript时间格式转换(今天,昨天,前天)
    移动web开发都会遇到的坑(会持续更新)
    javascript实现SHA1算法
    移动端重构--重置样式
    Grunt完整打包一个项目实例
    谈谈HTML5中的history.pushSate方法,弥补ajax导致浏览器前进后退无效的问题
    关于display:inline-block布局导致错位问题分析
  • 原文地址:https://www.cnblogs.com/chris-cp/p/7596089.html
Copyright © 2020-2023  润新知