package main

import (
"fmt"
) type Pointer struct {
x string
} func (this *Pointer) PrintX() {
fmt.Printf("X:%s\n", this.x)
} func (this *Pointer) SetX(str string) {
this.x = str
} type Value struct {
x string
} func (this Value) PrintX() {
fmt.Printf("X:%s\n", this.x)
} func (this Value) SetX(str string) {
this.x = str
} func main() {
p1 := Pointer{x: "Pointer"}
p1.PrintX()
p1.SetX("Pointer1")
p1.PrintX() p2 := &Pointer{}
p2.PrintX()
p2.SetX("Pointer2")
p2.PrintX() p3 := Value{x: "Value"}
p3.PrintX()
p3.SetX("Value1")
p3.PrintX() p4 := &Value{x: "value"}
p4.PrintX()
p4.SetX("Value2")
p4.PrintX()
}

运行结果:

X:Pointer
X:Pointer1
X:
X:Pointer2
X:Value
X:Value
X:value
X:value

说明:1 无论是T*作为receiver还是T类型作为接受者,都可以用实例、或者实例的指针调用函数,但是T*作为接受者将改变receiver的内容,而T类型改变的是副本,原始对象不会改变。

type Type struct {
} type PType struct {
} type Inter interface {
post()
} // 接收者非指针
func (t Type) post() {
} // 接收者是指针
func (t *PType) post() {
} func test() {
var it Inter
//var it *Inter //接口不能定义为指针
pty := &Type{}
it = ty // 将变量赋值给接口,OK
it.post() // 接口调用方法,OK, receiver 是T ty := Type{}
it = pty // 把指针变量赋值给接口,OK
it.post() // 接口调用方法,OK, receiver 是T pty2 := &PType{}
it = pty2 // 把指针变量赋值给接口,OK
it.post() // 接口调用方法,OK, receiver 是*T //ty2 := PType{}
//it = ty2 // 将变量赋值给接口,error
//it.post() // 接口调用方法,error, receiver 必须是T,而不能是T
}

详细代码:http://play.golang.org/p/KG8-Qb7gqM

为什么编译器不考虑我们的值是实现该接口的类型?接口的调用规则是建立在这些方法的接受者和接口如何被调用的基础上。下面的是语言规范里定义的规则,这些规则用来说明是否我们一个类型的值或者指针实现了该接口:

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

这条规则说的是如果我们用来调用特定接口方法的接口变量是一个指针类型,那么方法的接受者可以是值类型也可以是指针类型。显然我们的例子不符合该规则,因为我们传入 SendNotification 函数的接口变量是一个值类型。

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

这条规则说的是如果我们用来调用特定接口方法的接口变量是一个值类型,那么方法的接受者必须也是值类型该方法才可以被调用。显然我们的例子也不符合这条规则,因为我们 Notify 方法的接受者是一个指针类型。

语言规范里只有这两条规则,我通过这两条规则得出了符合我们例子的规则:

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

Interface也是引用类型。

goang Receiver & interface的更多相关文章

  1. QUICK START GUIDE

    QUICK START GUIDE This page is a guide aimed at helping anyone set up a cheap radio scanner based on ...

  2. golang实现rabbitmq消息队列失败尝试

    在工作中发现,有些时候消息因为某些原因在消费一次后,如果消息失败,这时候不ack,消息就回一直重回队列首部,造成消息拥堵. 如是有了如下思路: 消息进入队列前,header默认有参数 retry_nu ...

  3. go test 测试用例那些事(二) mock

    关于go的单元测试,之前有写过一篇帖子go test测试用例那些事,但是没有说go官方的库mock,很有必要单独说一下这个库,和他的实现原理. mock主要的功能是对接口的模拟,需要在写代码的时候定义 ...

  4. GoLang设计模式08 - 命令模式

    命令模式是一种行为型模式.它建议将请求封装为一个独立的对象.在这个对象里包含请求相关的全部信息,因此可以将其独立执行. 在命令模式中有如下基础组件: Receiver:唯一包含业务逻辑的类,命令对象会 ...

  5. golang监听rabbitmq消息队列任务断线自动重连接

    需求背景: goalng常驻内存任务脚本监听rbmq执行任务 任务脚本由supervisor来管理 当rabbitmq长时间断开连接会出现如下图 进程处于fatal状态 假如因为不可抗拒因素,rabb ...

  6. Receiver class com.mchange.v2.c3p0.impl.NewProxyResultSet does not define or inherit an implementation of the resolved method 'abstract boolean isClosed()' of interface java.sql.ResultSet.

    背景: Mayabtis+springboot项目,连接数据库发生异常 报错内容: java.lang.AbstractMethodError: Receiver class com.mchange. ...

  7. Tun/Tap interface tutorial

    Foreword: please note that the code available here is only for demonstration purposes. If you want t ...

  8. Interface Serializable

    public interface Serializable Serializability of a class is enabled by the class implementing the ja ...

  9. 关于Go 的 Interface

    最近在用Go语言写程序, 其中遇到一个场景:写了一个接口,3个实现接口的struct. 另外一个struct包含此接口,根据构造函数赋予不同的结构实现. 一开始struct里写的是接口的地址,但是在创 ...

随机推荐

  1. LeetCode(79) Word Search

    题目 Given a 2D board and a word, find if the word exists in the grid. The word can be constructed fro ...

  2. Action的实现方式

    [Pojo方式] 1.概述 Pojo(Plain Ordinary Java Object)称为简单Java类,其实就是一个JavaBean. 2.示例 /** * Pojo类方式实现Action * ...

  3. luogu3755 [CQOI2017]老C的任务

    扫描线水题. #include <algorithm> #include <iostream> #include <cstdio> using namespace ...

  4. 开始 python programming第三版案例分析

    最近研究python,打算将python programming第三版案例分析下 但是全书1600多页 比较费时 而且 介绍太多 感觉没有必要! python programming 堪称经典之作 第 ...

  5. mysql无法创建外键问题

    在阿里云上面安装配置了Mysql后,无法创建外键, 原因及解决方法: 选择InnoDB引擎,因为MyISAM引擎不支持外键,默默地说一句,MySQL真神奇

  6. pytorch中torch.unsqueeze()函数与np.expand_dims()

    numpy.expand_dims(a, axis) Expand the shape of an array. Insert a new axis that will appear at the a ...

  7. 有关git的配置

    git版本控制器总结 关于部分内容请参考:https://www.cnblogs.com/smuxiaolei/p/7484678.htmlgit是一个版本控制器,分布式管理:可以记录每次文件的改动, ...

  8. mysql通过mysqldump实现备份,脚本编写

    每日三点同步mysql备份任务 crontab -e 0 3 * * * sh /home/shell/mysql_bakup.sh >> /dev/null 2>&1 my ...

  9. Ubuntu 终端命令整理

    一.文件目录类 1.建立目录:mkdir 目录名 2.删除空目录:rmdir 目录名 3.无条件删除子目录: rm -rf 目录名 4.改变当前目录:cd 目录名 (进入用户home目录:cd ~:进 ...

  10. python 列表 字符串 转换

    列表转字符串python中的列表l = ['1','2','3','4']转成str型'1,2,3,4'','.join(l)这个方法,列表里都是字符串的话可以这样用.列表里是整数的情况可以用: &g ...