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语言接口内部布局和方法集详解的更多相关文章

  1. 集合类 Contains 方法 深入详解 与接口的实例

    .Net 相等性:集合类 Contains 方法 深入详解 http://www.cnblogs.com/ldp615/archive/2009/09/05/1560791.html 1.接口的概念及 ...

  2. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  3. Underscore _.template 方法使用详解

    为什么用「void 0」代替「undefined」 undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写. 事实上,undefined ...

  4. GridBagLayout布局管理器应用详解

    http://www.cnblogs.com/kungfupanda/p/7220217.html GridBagLayout布局管理器应用详解 很多情况下,我们已经不需要通过编写代码来实现一个应用程 ...

  5. 精讲RestTemplate第4篇-DELETE、PUT等请求方法使用详解

    本文是精讲RestTemplate第5篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  6. C#二次开发BIMFACE系列61 File Management文件管理服务接口二次开发及实战详解

    系列目录     [已更新最新开发文章,点击查看详细] 在我的博客<C#二次开发BIMFACE系列61 File Management文件管理服务接口二次开发及实战详解>最后列出了 Fil ...

  7. C#虚方法virtual详解

    转: http://www.cnblogs.com/jason_yjau/archive/2009/08/25/1553949.html C#虚方法virtual详解 在C++.Java等众多OOP语 ...

  8. 4.C#虚方法virtual详解

    C#虚方法virtual详解 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外. 虚拟函数从C#的程序编译的角度来看,它和其它一般的函数 ...

  9. Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解

    Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解 说明:Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解,加密算法,是现在每个软件项目里必须用到的内容. 广泛应用在包括 ...

随机推荐

  1. commonJS、AMD和CMD之间的区别

    JS中的模块规范(CommonJS,AMD,CMD),如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧, ...

  2. B - How Many Equations Can You Find dfs

    Now give you an string which only contains 0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9.You are asked to add the sig ...

  3. Robberies 杭电

    可怜的POIUYTREWQ最近想买下dota2的商品,但是手头缺钱.他想起了之前看过的一部大片,觉得抢银行也许是个不错的选择.他认为,坏人被抓是因为没有预先规划.于是他在之前的几个月对各大银行进行了一 ...

  4. frame/iframe多表单切换

    应用场景: 在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌页面上的元素无法直接定位.这时就 ...

  5. mac上搭建mysql环境配置和Navicat连接mysql

    mac上搭建mysql环境配置 1.下载mysql for mac: https://downloads.mysql.com/archives/community/ 注意:mysql版本要和你的MAC ...

  6. 使用 selenium 实现谷歌以图搜图爬虫

    使用selenium实现谷歌以图搜图 实现思路 原理非常简单,就是利用selenium去操作浏览器,获取到想要的链接,然后进行图片的下载,和一般的爬虫无异. 用到的技术:multiprocessing ...

  7. go 基础 结构体

    结构体是类型中带有成员的复合类型.go语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. go语言中的类型可以被实例化,使用new和&构造类型实例的类型是类型的指针. 结构体 ...

  8. tp5--路由的使用(初级)

    在配置文件夹下的route.php文件配置路由: 控制器: 运行结果:

  9. Linux系统硬件时间12小时制和24小时制表示设置

    目前的服务器status是下面这样的 服务器系统    centos7 Linux系统时间      Fri Mar 20 15:26:27 CST 2020 Linux系统硬件时间  Fri 20 ...

  10. Python 基础教程(第二版)笔记 (2) 字典

    P59 字典方法 1. clear 2. copy, deepcopy 3. fromkeys 4. get 比下标安全 5. has_key 6. items, iteritems 7. keys, ...