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/小程序接口传输常见的加密算法及详解,加密算法,是现在每个软件项目里必须用到的内容. 广泛应用在包括 ...
随机推荐
- Python-气象-大气科学-可视化绘图系列(一)——利用xarray读取netCDF文件并画图(代码+示例)
本文原创链接:https:////www.cnblogs.com/zhanling/p/12192978.html 1 import numpy as np import xarray as xr i ...
- 利用SSIS进行SharePoint 列表数据的ETL
好几年前写了一篇<SSIS利用Microsoft Connector for Oracle by Attunity组件进行ETL!>,IT技术真是日新月异,这种方式对于新的SQL SERV ...
- 你只要5行代码,拥有你的个性二维码,用Python生成动态二维码
如果想了解更多关于python的应用,可以私信我,或者点击下方链接自行获取,里面到资料都是免费的(http://t.cn/A6Zvjdun) 二维码满天飞,但是有没有想过Python也能制作出专属于自 ...
- 刚从一道题发现的一些东西,PHP笔记,关于extract和null 空字符串
队友发给我的一道extract变量的最基础的题目,他发现了一些问题,当传入shiyan=&flag=0时出flag,当传入shiyan=0&flag=0时不出flag,传入shiyan ...
- selemiun 下拉菜单、复选框、弹框定位识别
一.下拉菜单识别 对下拉框的操作,主要是通过Select 类里面的方法来实现的,所以需要new 一个Select 对象(org.openqa.selenium.support.ui.Select)来进 ...
- [linux] linux的top命令参数详解
简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...
- SpringCloud(一)学习笔记之项目搭建
[springcloud项目名称不支持下划线] 一.创建父项目 File---new---project: 填写项目信息: 默认即可,点击finish创建完成: 由于父项目只用到pom文件 所以把sr ...
- python web的进化历程
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 阶段1 socket服务端和客户端都自己编写 实现访问8080端口,返回一个'hello wo ...
- java实现自定义哈希表
哈希表实现原理 哈希表底层是使用数组实现的,因为数组使用下标查找元素很快.所以实现哈希表的关键就是把某种数据类型通过计算变成数组的下标(这个计算就是hashCode()函数 比如,你怎么把一个字符串转 ...
- centos7在命令行下安装图形界面
yum groupinstall "GNOME Desktop" "Graphical Administration Tools" ln -sf /lib/sy ...