Go语言接口内部布局和方法集详解
1. 接口值内部布局
如果用户定义的类型实现了某个接口类型声明的一组方法,那么这个用户定义的类型的值就可以赋给这个接口类型的值。这个赋值会把用户定义的类型的值存入接口类型的值。赋值完成后得到的值称为接口值。接口值是一个两个字长度的数据结构,第一个字包含一个指向内部表的指针。这个内部表叫作iTable,包含了所存储的值的类型信息和与这个值相关联的一组方法(也就是方法集)。第二个字是一个指向所存储值的指针。下图展示实体值赋值后接口值的内部布局:

实体值赋值后接口值的内部布局图
如果是一个指针赋值给接口的情况,类型信息会存储一个指向保存的类型的指针,而接口值第二个字依旧保存指向实体值的指针。如下图:

实体指针赋值后接口值的内部布局图
2. 方法集
方法集定义了接口的接受规则。方法集中定义了一组关联到给定类型的值或者指针的方法。定义方法时使用的接收者的类型决定了这个方法是关联到值,还是关联到指针,还是两个都关联。先看下Go语言规范里定义的方法集的规则:
| Values | Methods Receivers |
|---|---|
| T | (t T) |
| *T | (t T) and (t *T) |
Go语言对该规范的描述中说道,T类型的值的方法集只包含值接收者声明的方法(因为有些值的地址获取不到),而指向T类型的指针的方法集既包含值接收者声明的方法,也包含指针接收者声明的方法。听起来会有些绕,难以理解。如果我们从参数传递的角度是理解这句话获取更好理解:T类型的值只能传递给值接收者声明的方法,指向T类型的指针既能传递给值接收者声明的方法,也能传递给指针接收者声明的方法。
如果从接收者类型的视角来看方法集,就会比较好理解:
| Methods Receivers | Values |
|---|---|
| (t T) | T and *T |
| (t *T) | *T |
从接收者的视角来看的话,值接收者声明的方法能接受值类型和指针类型的参数,指针接收者声明的方法只能接受指针类型的参数。
3. 代码示例
3.1 如果接收者是值类型,用值调用和用指向值的指针调用都没有问题
package main
import (
"fmt"
)
type notifier interface {
notify()
}
type user struct {
name string
email string
}
func (u user) notify() {
fmt.Printf("sending user email to %s<%s>\n", u.name, u.email)
}
func sendNotification(n notifier) {
n.notify()
}
func main() {
u := user{name: "lisa",
email: "test@qq.com",
}
sendNotification(u)
sendNotification(&u)
}
3.2 如果接收者是指针类型,只能用指向值的指针来调用
package main
import (
"fmt"
)
type notifier interface {
notify()
}
type user struct {
name string
email string
}
func (u *user) notify() {
fmt.Printf("sending user email to %s<%s>\n", u.name, u.email)
}
func sendNotification(n notifier) {
n.notify()
}
func main() {
u := user{name: "lisa",
email: "test@qq.com",
}
// 这行代码会报如下错误:
// .\learn.go:29:18: cannot use u (type user) as type notifier in argument to sendNotification:
// user does not implement notifier (notify method has pointer receiver)
// sendNotification(u)
sendNotification(&u)
}
4. 参考书籍:
《Go语言实战》
Go语言接口内部布局和方法集详解的更多相关文章
- 集合类 Contains 方法 深入详解 与接口的实例
.Net 相等性:集合类 Contains 方法 深入详解 http://www.cnblogs.com/ldp615/archive/2009/09/05/1560791.html 1.接口的概念及 ...
- 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)
方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...
- Underscore _.template 方法使用详解
为什么用「void 0」代替「undefined」 undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写. 事实上,undefined ...
- GridBagLayout布局管理器应用详解
http://www.cnblogs.com/kungfupanda/p/7220217.html GridBagLayout布局管理器应用详解 很多情况下,我们已经不需要通过编写代码来实现一个应用程 ...
- 精讲RestTemplate第4篇-DELETE、PUT等请求方法使用详解
本文是精讲RestTemplate第5篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- C#二次开发BIMFACE系列61 File Management文件管理服务接口二次开发及实战详解
系列目录 [已更新最新开发文章,点击查看详细] 在我的博客<C#二次开发BIMFACE系列61 File Management文件管理服务接口二次开发及实战详解>最后列出了 Fil ...
- C#虚方法virtual详解
转: http://www.cnblogs.com/jason_yjau/archive/2009/08/25/1553949.html C#虚方法virtual详解 在C++.Java等众多OOP语 ...
- 4.C#虚方法virtual详解
C#虚方法virtual详解 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外. 虚拟函数从C#的程序编译的角度来看,它和其它一般的函数 ...
- Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解
Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解 说明:Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解,加密算法,是现在每个软件项目里必须用到的内容. 广泛应用在包括 ...
随机推荐
- F - What Is Your Grade?
“Point, point, life of student!” This is a ballad(歌谣)well known in colleges, and you must care about ...
- 原创zookeeper3.4.6集群安装
tar -zxvf zookeeper-3.4.6.tar.gz -C /home/hadoop/ vi ~/.bash_profile export ZOOKEEPER_HOME=/home/had ...
- vue2.x学习笔记(十四)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12602256.html. 组件的Prop Prop是组件之间通信的一个重要途径,了解其知识十分重要. Prop的大 ...
- windows搭建Selenium
安装 pip install -U selenium 安装浏览器驱动 用不同的浏览器需要安装不同的驱动,驱动放置的路径添加到path中. Firefox geodriver Chrome 下载驱动Ch ...
- [html]浏览器标签小图标LOGO简单设置
方式一:如果是一个项目一个LOGO 的话,直接接把图片像素设置成16x16像素,然后改名favicon.ico放在项目根部目录就可以,自动识别的! 方式二:简单设置! 首先找一个图片把像素设置成16x ...
- [javascript]JS获取当前时间戳的方法
JavaScript 获取当前时间戳: 第一种方法:(这种方法只精确到秒) var timestamp = Date.parse(new Date()); 结果:1280977330000 第二种方法 ...
- java 方法的重载、重写与重构
首先我们要知道重载.重写.重构的区别 重载:指的是在同一个类中,方法名相同,但是参数数量.参数类型或者返回类型不同的方法就叫做重载. 重写: 重写分两种.第一种的是在子类继承父类的情况下,通过@Ove ...
- C# 序列化之二进制
序列化:又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方. 一般有三种方式:1.是使用BinaryF ...
- 微信小程序基本知识
逻辑实现 1 使用动态数据展示列表(可以考虑使用wx:for属性配合动态数组渲染全部列表项,以减少WXML页面的代码量) eg: <view class='listGroup' wx:for= ...
- 模拟电磁曲射炮_H题 方案分析【2019年电赛】【刘新宇qq522414928】
请查看我的有道云笔记: 文档:电磁曲射炮分析.note链接:http://note.youdao.com/noteshare?id=26f6b6febc04a8983d5efce925e92e21