使用方法集与接口

作用于变量上的方法实际上是不区分变量到底是指针还是值的。当碰到接口类型值时,这会变得有点复杂,原因是接口变量中存储的具体值是不可寻址的,幸运的是,如果使用不当编译器会给出错误。考虑下面的程序:

package main

import (
    "fmt"
)

type List []int

func (l List) Len() int {
    return len(l)
}

func (l *List) Append(val int) {
    *l = append(*l, val)
}

type Appender interface {
    Append(int)
}

func CountInto(a Appender, start, end int) {
    for i := start; i <= end; i++ {
        a.Append(i)
    }
}

type Lener interface {
    Len() int
}

func LongEnough(l Lener) bool {
    return l.Len()*10 > 42
}

func main() {
    // A bare value
    var lst List
    // compiler error:
    // cannot use lst (type List) as type Appender in argument to CountInto:
    //       List does not implement Appender (Append method has pointer receiver)
    // CountInto(lst, 1, 10)
    if LongEnough(lst) { // VALID:Identical receiver type
        fmt.Printf("- lst is long enough\n")
    }

    // A pointer value
    plst := new(List)
    CountInto(plst, 1, 10) //VALID:Identical receiver type
    if LongEnough(plst) {
        // VALID: a *List can be dereferenced for the receiver
        fmt.Printf("- plst is long enough\n")
    }
}

讨论

在 lst 上调用 CountInto 时会导致一个编译器错误,因为 CountInto 需要一个 Appender,而它的方法 Append 只定义在指针上。 在 lst 上调用 LongEnough 是可以的因为 'Len' 定义在值上。
在 plst 上调用 CountInto 是可以的,因为 CountInto 需要一个 Appender,并且它的方法 Append 定义在指针上。 在 plst 上调用 LongEnough 也是可以的,因为指针会被自动解引用。

总结

在接口上调用方法时,必须有和方法定义时相同的接收者类型或者是可以从具体类型 P 直接可以辨识的:

指针方法可以通过指针调用
值方法可以通过值调用
接收者是值的方法可以通过指针调用,因为指针会首先被解引用
接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址
将一个值赋值给一个接口时,编译器会确保所有可能的接口方法都可以在此值上被调用,因此不正确的赋值在编译期就会失败。

译注

Go 语言规范定义了接口方法集的调用规则:

类型 *T 的可调用方法集包含接受者为 *TT 的所有方法集
类型 T 的可调用方法集包含接受者为 T 的所有方法
类型 T 的可调用方法集不包含接受者为 *T 的方法

转载地址

https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/11.6.md

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简化数据库设计和管理。 使用友好的GUI工具编辑,记录和浏览复杂的数据库。 使用布局简化数据库设计。 通过关注数据库架构的特定部分,可以更好地理解复杂的数据库。 使用我们直观的UI,可以很容易地为复杂模式创建数据库设计。 该界面使您能够简单地通过拖放或双击来执行复杂的动作。 同时轻松浏览来自多个表的数据。 无需成为SQL专家! DbSchema将帮助您编写SQL查询。 具有文本自动补全功能的强大编辑器。 支持所有SQL和NoSQL数据库 DbSchema通过创建自己的保存到项目文件中的架构的本地副本以独特的方式工作。 本地项目文件可以: 使用GIT或任何其他版本控制系统与团队一起处理项目文件 将设计保存到XML项目文件并使用任何文本编辑器将其打开 在多台服务器上部署一个架构 在不同版本之间迁移一个架构并生成迁移脚本 没有数据库连接的设计架构( 脱机 ) 为您的数据库架构生成PDF或交互式HTML5文档。 DbSchema可以比较不同数据库或不同项目文件之间的方案,显示它们并生成迁移脚本。 如果数据库缺少外键,则可以创建将仅保存在DbSchema中的虚拟外键 。 它们将帮助您更好地了解数据库。 这些外键用绿色标记。 使用可配置,随机和反向正则表达式 。 使用JDBC驱动程序连接到任何数据库,对结构进行反向工程,并将其作为ER图查看。 利用具有文本自动完成功能,Groovy脚本支持,脚本和查询执行功能的强大SQL编辑器。 将数据从CSV,XML等加载到数据库中。 使用文本输入,按钮和图表构建简单的Web报表或应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值