Go 语言基础(六) 之 接口

1、接口的定义

保留字 interface 被赋予了多种不同的含义。

每个类型都有接口,意 味着对那个类型定义了方法集合

定义结构和结构的方法:

type S struct { i int }

func (p *S) Get() int { return p.i }

func (p *S) Put(v int) { p.i = v }

也可以定义接口类型,仅仅是方法的集合。

这里定义了一个有两个方法的接口 I:

type I interface {

Get() int

Put(int)

}

对于接口 I,S 是合法的实现,因为它定义了 I 所需的两个方法。

注意,即便是没有明确定义 S 实现了 I,这也是正确的。

func f(p I){ // 定义一个函数接受一个接口类型作为参数

fmt.Println(p.Get()) // p实现了接口I,必须有Get()方法

p.Put(1) // Put() 方法是类似的

}

这里的变量 p 保存了接口类型的值。因为 S 实现了 I,可以调用 f 向其传递 S 类型的值的指针:

var s S; f(&s)

获取 s 的地址,而不是 S 的值的原因,是因为在 s 的指针上定义了方法,

这并不是必须的——可以定义让方法接受值——但是这样的话 Put 方法就不会像期望的那样工作了。

Go 联合了接口值、静态类型检查、运行时动态转换,以及无须明确定义类型适 配一个接口

定义另外一个类型同样实现了接口 I:

type R struct { i int }

func (p *R) Get() int { return p.i }

func (p *R) Put(v int) { p.i = v }

函数 f 现在可以接受 R 个 S 类型的变量。假设需要在函数 f 中知道实际的类型。

在 Go 中可以使用 type switch 得到。

func f(p I) {

switcht:=p.(type){ // 类型判断。在 switch 语句中使用 (type)。保存类型到变量 t;

case *S: // p的实际类型是S的指针;

case *R: // p的实际类型是R的指针;

case S: // p的实际类型是S;

case R: // p的实际类型是R;

default: // 实现了 I 的其他类型。

}

}

在 switch 之外使用 (type) 是非法的。类型判断不是唯一的运行时得到类型的方法。

为了在运行时得到类型,同样可以使用 “comma, ok” 来判断一个接口类型

是否实现了某个特定接口:

if t, ok := something.(I); ok {

// 对于某些实现了接口 I 的

// t 是其所拥有的类型

}

确定一个变量实现了某个接口,可以使用:

t := something.(I)

2、空接口

由于每个类型都能匹配到空接口: interface{}。

我们可以创建一个接受空接口 作为参数的普通函数:

func g(something interface{}) int {

return something.(I).Get()

}

在这个函数中的 return something.(I).Get() 是有一点窍门的。

值 something 具有类型 interface{},这意味着方法没有任何约束:它能包含任何类型。

.(I) 是 类型断言,用于转换 something 到 I 类型的接口。

如果有这个类型,则可以调用 Get() 函数。因

此,如果创建一个 *S 类型的新变量,也可以调用 g(),因为 *S 同 样实现了空接口。

s = new(S)

fmt.Println(g(s));

调用 g 的运行不会出问题,并且将打印 0。

如果调用 g() 的参数没有实现 I 会带来一个麻烦:

i:=5 ←声明i 是一个``该死的‘‘int

fmt.Println(g(i))

这能编译,但是当运行的时候会得到:

panic: interface conversion: int is not main.I: missing method Get

这是绝对没问题,内建类型 int 没有 Get() 方法。

3、方法

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

可以在任意类型上定义方法(除了非本地类型,包括内建类型:int 类型不能有方法)。

然而可以新建一个拥有方法的整数类型。

type Foo int

func (self Foo) Emit() {

fmt.Printf("%v", self)

}

type Emitter interface {

Emit()

}

接口类型的方法

接口定义为一个方法的集合。方法包含实际的代码。

换句话说,一个接口就是 定义,而方法就是实现。

因此,接收者不能定义为接口类型,

这样做的话会引 起 invalid receiver type ... 的编译器错误。

注:接收者类型必须是 T 或 *T,这里的 T 是类型名。

T 叫做接收者基础类型或简称基础类型。

基础类型一定不能使指针或接口类型,并且定义在与方法相同的包中。

接口指针

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

实际上创建接口值的指针 也是非法的。

4、接口名字

根据规则,单方法接口命名为方法名加上 -er 后缀:Reader,Writer,Formatter 等。

有一堆这样的命名,高效的反映了它们职责和包含的函数名。

Read,Write, Close,Flush,String 等等有着规范的声明和含义。

为了避免混淆,除非有类似 的声明和含义,否则不要让方法与这些重名。

相反的,如果类型实现了与众所 周知的类型相同的方法,

那么就用相同的名字和声明;将字符串转换方法命名 为 String 而不是 ToString。

5、自省和反射

了解一下定义在 Person 的定义中的 “标签”(这里命名为 “namestr”)。

为了做到这个,需要 reflect 包(在 Go 中没有其他方法)。

要记得, 查看标签意味着返回类型的定义。

因此使用 reflect 包来指出变量的类型, 然后 访问标签。

时间: 2024-11-05 13:44:04

Go 语言基础(六) 之 接口的相关文章

C#语言基础

第一部分 了解C# C#是微软公司在2000年7月发布的一种全新且简单.安全.面向对象的程序设计语言,是专门为.NET的应用而开发的.体现了当今最新的程序设计技术的功能和精华..NET框架为C#提供了一个强大的.易用的.逻辑结构一致的设计环境.其特点: 语言简洁 保留了C++的强大功能: 快速应用开发功能: 语言的的自由性: 强大的Web服务器控件: 支持跨平台: 与XML相融合: 第二部分 C#语言基础: 一.C#项目的组成结构: 1.项目后缀 .config——配置文件(存放配置参数文件)

C语言基础(转载自大海笔记)

# C语言基础2015年03月26日10:04:411.    语言排行榜C——java——objective-C2.    进制:进制:进位机制.用普通的话讲,应该为人为的定义一种度量来标识一样东西.计算机常用的进制有:十进制.二进制.八进制和十六进制.?    十进制:0-9(十个指头)(进制表示基数:10)?    二进制:0,1(基数为2)?    八进制:0-7(基数为8)?    十六进制:0-9,A-F(基数为16)    可以有很多进制,比如分钟为60进制等等.3.    位权为

c语言基础知识要点

C语言程序的构成 与C++.Java相比,C语言其实很简单,但却非常重要.因为它是C++.Java的基础.不把C语言基础打扎实,很难成为程序员高手. 一.C语言的结构 先通过一个简单的例子,把C语言的基础打牢. /* clang01_1.c */ #include <stdio.h> int main(void) { printf("这是劝学网的C语言教程.\n"); return 0; } C语言的结构要掌握以下几点: C语言的注释是/* ··· */,而不是//···,

JavaScript基础---语言基础(4)

函数,对象和数组 学习要点: 1.函数声明 2.return返回值 3.arguments对象 4.Object类型 5.Array类型 6.对象中的方法 函数是定义一次但却可以调用或执行任意多次的一段JS代码.函数有时会有参数,即函数被调用时指定了值的局部变量.函数常常使用这些参数来计算一个返回值,这个值也成为函数调用表达式的值. 一.函数声明 函数对任何语言来说都是一个核心的概念.通过函数可以封装任意多条语句,而且可以在任何地方.任何时候调用执行.ECMAScript中的函数使用functi

C#语言基础(一)

Visual Studio.NET的集成开发环境 一.语言基础 (一)C#项目的组成结构: 1.项目结构 1.1 项目后缀 .config--配置文件(存放配件参数文件) .csproj--项目文件(管理文件项) .sln--解决方案文件(管理项目) .cs源文件(程序代码) 注:后缀不同代表文件类型也不同,这些文件类型会在“解决方案资源管理器”中看到. 1.2 函数的四要素:名称,输入,输出,加工. 1.3 主函数:输入语句,输出语句. Static void Maid(string[] ar

second day C#语言基础

第一部分 了解C# 一.C#的定义及其特点 C#是微软公司在2000年7月发布的的一种全新且简单.安全.面向对象的程序设计语言,是专门为.NET的应用而开发的语言.它吸收了C++.Visual Basic.Delphi.Java等语言的有点,体现了当今最新的程序设计技术的功能和精华.NET框架为C#提供了一个强大的.易用的.逻辑结构一直的程序设计环境.同时,公共语言运行时(Common Language Runtime)为C#程序语言提供了一个托管的运行时环境,是程序比以往更加稳定.安全.其特点

20165310 学习基础和C语言基础调查

学习基础和C语言基础调查 做中学体会 阅读做中学之后,了解老师关于五笔练习.减肥.乒乓和背单词的经历,不禁联想到自己学古筝的经历. 成功的经验 兴趣 我其实小时候学过一段时间古筝,但是那时候是因为父母的要求,自己并不喜欢,后来就终止了.直到再过了几年自己对于古筝产生了兴趣,主动要求重新学习古筝,一直坚持到了最后. 专注 说来惭愧,我练琴从来不是定时定量的,而是根据心情和专注程度来,对于我来说,心不在焉的练习两个小时的效率没有专注练习半小时高.状态不好时当天我会放弃练习,状态好的时候连续练习几个小

20165318 预备作业二 学习基础和C语言基础调查

20165318 学习基础和C语言基础调查 技能学习经验 我们这一代人,或多或少的都上过各种兴趣班,舞蹈钢琴画画书法,我也是如此.可这些技能中,唯一能拿的出手的就是舞蹈了.按照<优秀的教学方法---做教练与做中学>中的标准:一项技能的掌握程度分为:新手/高级初学者/合格者/精通/专家.我认为自己尚且只达到合格者的程度,并不能说自己的水平凌驾于大多数人之上. 从4岁学到14岁,这些年的学习,还是带给我很多启发,要学好一项技能,要具备以下几点: 兴趣:兴趣是最好的老师.我小时候就对舞蹈很有兴趣,看

20165323 学习基础和C语言基础调查

20165323 学习基础和C语言基础调查 一.技能学习心得 1.你有什么技能比大多人更好? 我觉得我羽毛球打的还行,不能说打得比大多数人好,但是对于一些打羽毛球的要领还是掌握的. 2.针对这个技能的获取你有什么成功的经验? 想要打好羽毛球,首先你得建立起对它的兴趣.你对打羽毛球这件事产生了兴趣,你才能够更加投入地去练习它,这样子你的效率才高.如果你对这件事没有兴趣,那么你对于这件事的态度或许只是在应付而已,这样子就不会有任何的意义,也很难提升自己的水平.其次,便是坚持.常言道:"宝剑锋从磨砺出

20165103学习基础和C语言基础调查

20165103学习基础和C语言基础调查 学习基础和C语言基础调查 技能及其学习经验 在阅读老师做中学系列文章的时候,读到了一句话: 开发极点起因主要是个人兴趣爱好和工作需要. -- 引用自<做中学之五笔输入法实践教程> 回顾自己的不断的学习实践过程中,自己所学得比较好的知识.技能大多都是由于自身的兴趣加上工作需要才一步步逐渐掌握.在最近掌握的几个技能当中,太极拳这项技能勉强可以达到一个较高的水平. 学习经验 入门 首先还是因为对传统武术有一定兴趣,加之可以锻炼身体,便决定加入学校社团,开始学