在 Go 中,类型可以定义接收此类型的函数,即方法。每个类型都有接口,意味着对那个类型定义了方法集合。

下面定义了结构体类型 S 以及它的两个方法:

type S struct { i int }
func (p *S) Get() int { return p.i }
func (p *S) Put(v int) { p.i = v }

方法

方法就是有接收者的函数。

可以在除了非本地类型(包括内建类型,比如 int)的任意类型上定义方法。然而可以为内建类型定义别名,然后就可以为别名定义方法。如

type Foo int // 为 int 定义别名 Foo
func (self Foo) Emit() {
fmt.Printf("%v", self)
}

接口

接口定义为一个方法的集合。方法包含实际的代码。换句话说,一个接口就是定义,而方法就是实现。因此,接收者不能定义为接口类型,这样做的话会引起 invalid receiver type … 的编译器错误。

来自语言说明书的权威内容:

接收者类型必须是T 或*T,这里的 T 是类型名。 T 叫做接收者基础类型或简称基础类型。基础类型一定不能是指针或接口类型,并且定义在与方法相同的包中。

// 定义了有两个方法的接口 I,结构 S 实现了此接口
type I interface {
Get() int
Put( int)
}

可以定义接口类型的变量(接口值)作为函数的参数,实现了此接口的类型的变量可以作为实参传递给该接口变量并调用其方法。

func f(p I) {
fmt.Println(p.Get())
p.Put(1)
} var s S
f(&s) // S 类型的变量 s 作为实参传给接口。取地址是因为在 s 的指针上定义了方法,这样可以修改 s;
// 如果在 s 上定义方法,则修改的只是 s 的副本

在 Go 中创建指向接口的指针是无意义的。创建接口值的指针也是非法的。

接口类型判断

在 Go 中,要判断传递给接口值的变量类型,可以在使用 type switch 得到。(type)只能在 switch 中使用。

// 另一个实现了 I 接口的 R 类型
type R struct { i int }
func (p *R) Get() int { return p.i }
func (p *R) Put(v int) { p.i = v } func f(p I) {
switch t := p.(type) { // 判断传递给 p 的实际类型
case *S: // 指向 S 的指针类型
case *R: // 指向 R 的指针类型
case S: // S 类型
case R: // R 类型
default: //实现了 I 接口的其他类型
}
}

若要在 switch 外判断一个接口类型是否实现了某个接口,可以使用“逗号 ok ”。

value, ok := Interfacevariable.(implementType)

其中 Interfacevariable 是接口变量(接口值),implementType 为实现此接口的类型,value 返回接口变量实际类型变量的值,如果该类型实现了此接口返回 true

type I interface{ // 有一个方法的接口 I
Get() Int
} type Int int // Int 类型实现了 I 接口
func (i Int) Get() Int{
return i
} var myint Int = 5
var inter I = myint // 变量赋值给接口
val, ok := inter.(Int)
fmt.Printf("%v, %v", val, ok) // 输出为:5,true

空接口

每种类型都能匹配到空接口:interface{}。空接口类型对方法没有任何约束(因为没有方法),它能包含任意类型,也可以实现到其他接口类型的转换。如果传递给该接口的类型变量实现了转换后的接口则可以正常运行,否则出现运行时错误。

func g(si interface{}) int {
return si.(I).Get()
}
s = new(S)
g(s) // (I) 将 si 转换到 I 类型的接口,s 实现了 Get 方法,因此可以调用 g() i := 5
g(i) // 运行时出错,因为 int 型没有 Get 方法

还可以在接口中列出另一个接口,如

type Interface interface {
sort.Interface // 另一个接口
Push(x interface{})
Pop() interface{}
}

自省和反射

Go 方法、接口的更多相关文章

  1. go 函数 方法 接口

    概论 函数 方法 接口 概论 方法在编译时静态绑定,依托于具体的类型 接口对应的方法是在运行时动态绑定 进程内初始化顺序 初始化导入包的常量和变量(可以导出的变量)--->包的init函数,不同 ...

  2. JVM 专题十四:本地方法接口

    1. 本地方法接口 2. 什么是本地方法? 简单来讲,一个Native Method就是一个Java调用非Java代码的接口.一个Native Method是这样一个java方法:该方法的实现由非Ja ...

  3. JVM--先说本地方法接口

    本地方法接口 在讲Java虚拟机运行时数据区中本地方法栈之前,我们先来说说运行时数据区之外的一个叫本地方法接口的东西简称JNI(Java Native Interface) 简单来讲,一个Native ...

  4. C# 工厂模式+虚方法(接口、抽象方法)实现多态

    面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...

  5. Java8函数式接口/Lambda表达式/接口默认方法/接口静态方法/接口冲突方法重写/lambda表达式指定泛型类型等

    一:函数式接口 1.函数式接口的概念就是此接口必须有且只能有一个抽象方法,可以通过@FunctionalInterface来显示规定(类似@Override),但是没有此注解的但是只有一个抽象方法的接 ...

  6. OpenJDK源码研究笔记(十四):三种经典的设计方法,接口,接口-抽象类-具体实现类,接口-具体实现类

    在研究OpenJDK源码过程中,我发现常用的设计方法就是2种:接口,接口-抽象类-具体实现类 . 在一些其它开源框架和业务开发中,经常存在着第3种设计,接口-具体实现类. 1.只有接口,没有实现类. ...

  7. C# 3.0 扩展方法&接口

    namespace ExtensionInterfaceMethod { class Program { static void Main(string[] args) { //使用接口变量来调用扩展 ...

  8. jvm入门及理解(五)——运行时数据区(虚拟机栈)和本地方法接口

    一.虚拟机栈背景 由于跨平台性的设计,java的指令都是根据栈来设计的.不同平台CPU架构不同,所以不能设计为基于寄存器的. 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要 ...

  9. jvm-本地方法接口

    什么是本地方法 简单地讲,一个Native Methodt是一个Java调用非Java代码的接囗.一个Native Method是这样一个Java方法:该方法的实现由非Java语言实现,比如C.这个特 ...

  10. Golang 函数 方法 接口的简单介绍

    函数 函数是基本的代码块,通常我们会将一个功能封装成一个函数,方便我们调用,同时避免代码臃肿复杂. 函数的基本格式 func TestFunc(a int, b string) (int, strin ...

随机推荐

  1. 2019 牛客暑期多校 B generator 1 (矩阵快速幂+倍增)

    题目:https://ac.nowcoder.com/acm/contest/885/B 题意:给你x0,x1,让你求出xn,递推式时xn=a*xn-1+b*xn-2 思路:这个n特别大,我自己没有摸 ...

  2. MySQL教程和使用手册

    MySQL 教程 MySQL 教程.MySQL 安装.MySQL 管理.MySQL PHP 语法.MySQL 连接.MySQL 创建数据库.MySQL 删除数据库.MySQL 选择数据库.MySQL ...

  3. php开发面试题---php 对swoole的理解

    php开发面试题---php 对swoole的理解 一.总结 一句话总结: 以战养学,实例驱动 swoole是披着PHP外衣的C程序:其实就是c.java那些语言里面的高阶功能:比如 持久连接.异步通 ...

  4. Python | 安装和配置智能提示插件Anaconda (转)

    作为Python开发环境的Sublime Text 3,有了Anaconda就会如虎添翼.Anaconda是目前最流行也是最有威力的Python代码提示插件. 工具/原料   Sublime Text ...

  5. Openstack组件部署 — 将一个自定义 Service 添加到 Keystone

    目录 目录 Keystone 认证流程 让 Keystone 为一个新的项目 Service 提供验证功能 最后 Keystone 认证流程 User 使用凭证(username/password) ...

  6. Tomcat负载均衡、调优核心应用进阶学习笔记(二):Tomcat前世今生、安装、配置文件详细说明、tomcat应用程序部署、webapp 体系结构、tomcat运行方式

    文章目录 Tomcat前世今生 安装 配置文件详细说明 tomcat应用程序部署 webapp 体系结构 tomcat运行方式 Tomcat前世今生 java体系: 1 java程序设计语言 2 ja ...

  7. 【单例模式】懒汉式的线程安全问题 volatile的作用

    原文链接:https://blog.csdn.net/Activity_Time/article/details/96496579 ****** 1. 懒汉式的Java实现 public class ...

  8. linux替换rm命令,防止误删

    1. 在/home/username/ 目录下新建一个目录,命名为:.trash 2.. 在/home/username/tools/目录下,新建一个shell文件,命名为: remove.sh #! ...

  9. Django框架(十八)—— CBV源码分析、restful规范、restframework框架

    目录 CBV源码分析.restful规范.restframework框架 一.CBV源码分析 1.url层的使用CBV 2.as_view方法 3.view方法 4.dispatch方法(可以在视图层 ...

  10. PHP数组循环遍历的几种方式

    PHP数组循环遍历 1.for循环 <?php //语法 for (init counter; test counter; increment counter) { code to be exe ...