教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Go语言基础之接口

Go语言基础之接口

发布时间:2022-01-24   编辑:jiaochengji.com
教程集为您提供Go语言基础之接口等资源,欢迎您收藏本站,我们将为您提供最新的Go语言基础之接口资源
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"/></svg>

<h3>文章目录</h3> <ul><li>Go语言基础之接口</li><li>接口</li><li>接口类型</li><li>为什么要使用接口</li><li>接口的定义</li><li>实现接口的条件</li><li>接口类型变量</li><li>值接收者和指针接收者实现接口的区别</li><li>值接收者实现接口</li><li>指针接收者实现接口</li><li>面试题</li><li>类型与接口的关系</li><li>一个类型实现多个接口</li><li>多个类型实现同一接口</li><li>接口嵌套</li><li>空接口</li><li>空接口的定义</li><li>空接口的应用</li><li>空接口作为函数的参数</li><li>空接口作为map的值</li><li>类型断言</li><li>接口值</li></ul>

<h1>Go语言基础之接口</h1>

接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。

<h1>接口</h1> <h1>接口类型</h1>

在Go语言中接口(interface)是一种类型,一种抽象的类型。

<code>interface</code>是一组<code>method</code>的集合,是<code>duck-type programming</code>的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。

为了保护你的Go语言职业生涯,请牢记接口(interface)是一种类型。

<h1>
为什么要使用接口</h1> <pre><code class="lang-go hljs"><span class="token keyword">type</span> Cat <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>c Cat<span class="token punctuation">)</span> <span class="token function">Say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>喵喵喵<span class="token operator">&</span>quot<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">type</span> Dog <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d Dog<span class="token punctuation">)</span> <span class="token function">Say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>汪汪汪<span class="token operator">&</span>quot<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> c <span class="token operator">:=</span> Cat<span class="token punctuation">{</span><span class="token punctuation">}</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>猫<span class="token punctuation">:</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span><span class="token function">Say</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> d <span class="token operator">:=</span> Dog<span class="token punctuation">{</span><span class="token punctuation">}</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>狗<span class="token punctuation">:</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> d<span class="token punctuation">.</span><span class="token function">Say</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

上面的代码中定义了猫和狗,然后它们都会叫,你会发现main函数中明显有重复的代码,如果我们后续再加上猪、青蛙等动物的话,我们的代码还会一直重复下去。那我们能不能把它们当成“能叫的动物”来处理呢?

像类似的例子在我们编程过程中会经常遇到:

比如一个网上商城可能使用支付宝、微信、银联等方式去在线支付,我们能不能把它们当成“支付方式”来处理呢?

比如三角形,四边形,圆形都能计算周长和面积,我们能不能把它们当成“图形”来处理呢?

比如销售、行政、程序员都能计算月薪,我们能不能把他们当成“员工”来处理呢?

Go语言中为了解决类似上面的问题,就设计了接口这个概念。接口区别于我们之前所有的具体类型,接口是一种抽象的类型。当你看到一个接口类型的值时,你不知道它是什么,唯一知道的是通过它的方法能做什么。

<h1>
接口的定义</h1>

Go语言提倡面向接口编程。

每个接口由数个方法组成,接口的定义格式如下:

<pre><code class="lang-go hljs"><span class="token keyword">type</span> 接口类型名 <span class="token keyword">interface</span><span class="token punctuation">{</span> 方法名<span class="token function">1</span><span class="token punctuation">(</span> 参数列表<span class="token number">1</span> <span class="token punctuation">)</span> 返回值列表<span class="token number">1</span> 方法名<span class="token function">2</span><span class="token punctuation">(</span> 参数列表<span class="token number">2</span> <span class="token punctuation">)</span> 返回值列表<span class="token number">2</span> … <span class="token punctuation">}</span> </code></pre>

其中:

<ul><li>接口名:使用<code>type</code>将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加<code>er</code>,如有写操作的接口叫<code>Writer</code>,有字符串功能的接口叫<code>Stringer</code>等。接口名最好要能突出该接口的类型含义。</li><li>方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。</li><li>参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。</li></ul>

举个例子:

<pre><code class="lang-go hljs"><span class="token keyword">type</span> writer <span class="token keyword">interface</span><span class="token punctuation">{</span> <span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">}</span> </code></pre>

当你看到这个接口类型的值时,你不知道它是什么,唯一知道的就是可以通过它的Write方法来做一些事情。

<h1>
实现接口的条件</h1>

一个对象只要全部实现了接口中的方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表

我们来定义一个<code>Sayer</code>接口:

<pre><code class="lang-go hljs"><span class="token comment">// Sayer 接口</span> <span class="token keyword">type</span> Sayer <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

定义<code>dog</code>和<code>cat</code>两个结构体:

<pre><code class="lang-go hljs"><span class="token keyword">type</span> dog <span class="token keyword">struct</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">type</span> cat <span class="token keyword">struct</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> </code></pre>

因为<code>Sayer</code>接口里只有一个<code>say</code>方法,所以我们只需要给<code>dog</code>和<code>cat</code>分别实现<code>say</code>方法就可以实现<code>Sayer</code>接口了。

<pre><code class="lang-go hljs"><span class="token comment">// dog实现了Sayer接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d dog<span class="token punctuation">)</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>汪汪汪<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// cat实现了Sayer接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>c cat<span class="token punctuation">)</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>喵喵喵<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

接口的实现就是这么简单,只要实现了接口中的所有方法,就实现了这个接口。

<h1>
接口类型变量</h1>

那实现了接口有什么用呢?

接口类型变量能够存储所有实现了该接口的实例。 例如上面的示例中,<code>Sayer</code>类型的变量能够存储<code>dog</code>和<code>cat</code>类型的变量。

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x Sayer <span class="token comment">// 声明一个Sayer类型的变量x</span> a <span class="token operator">:=</span> cat<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 实例化一个cat</span> b <span class="token operator">:=</span> dog<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 实例化一个dog</span> x <span class="token operator">=</span> a <span class="token comment">// 可以把cat实例直接赋值给x</span> x<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 喵喵喵</span> x <span class="token operator">=</span> b <span class="token comment">// 可以把dog实例直接赋值给x</span> x<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 汪汪汪</span> <span class="token punctuation">}</span> </code></pre> <h1>
值接收者和指针接收者实现接口的区别</h1>

使用值接收者实现接口和使用指针接收者实现接口有什么区别呢?接下来我们通过一个例子看一下其中的区别。

我们有一个<code>Mover</code>接口和一个<code>dog</code>结构体。

<pre><code class="lang-go hljs"><span class="token keyword">type</span> Mover <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">type</span> dog <span class="token keyword">struct</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> </code></pre> <h1>
值接收者实现接口</h1> <pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token punctuation">(</span>d dog<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>狗会动<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

此时实现接口的是<code>dog</code>类型:

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x Mover <span class="token keyword">var</span> wangcai <span class="token operator">=</span> dog<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 旺财是dog类型</span> x <span class="token operator">=</span> wangcai <span class="token comment">// x可以接收dog类型</span> <span class="token keyword">var</span> fugui <span class="token operator">=</span> <span class="token operator">&</span>amp<span class="token punctuation">;</span>dog<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 富贵是*dog类型</span> x <span class="token operator">=</span> fugui <span class="token comment">// x可以接收*dog类型</span> x<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

从上面的代码中我们可以发现,使用值接收者实现接口之后,不管是dog结构体还是结构体指针*dog类型的变量都可以赋值给该接口变量。因为Go语言中有对指针类型变量求值的语法糖,dog指针<code>fugui</code>内部会自动求值<code>*fugui</code>。

<h1>
指针接收者实现接口</h1>

同样的代码我们再来测试一下使用指针接收者有什么区别:

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token punctuation">(</span>d <span class="token operator">*</span>dog<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>狗会动<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x Mover <span class="token keyword">var</span> wangcai <span class="token operator">=</span> dog<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 旺财是dog类型</span> x <span class="token operator">=</span> wangcai <span class="token comment">// x不可以接收dog类型</span> <span class="token keyword">var</span> fugui <span class="token operator">=</span> <span class="token operator">&</span>amp<span class="token punctuation">;</span>dog<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 富贵是*dog类型</span> x <span class="token operator">=</span> fugui <span class="token comment">// x可以接收*dog类型</span> <span class="token punctuation">}</span> </code></pre>

此时实现<code>Mover</code>接口的是<code>*dog</code>类型,所以不能给<code>x</code>传入<code>dog</code>类型的wangcai,此时x只能存储<code>*dog</code>类型的值。

<h1>
面试题</h1>

请问下面的代码是否能通过编译?

<pre><code class="lang-go hljs"><span class="token keyword">type</span> People <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">Speak</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>stu <span class="token operator">*</span>Stduent<span class="token punctuation">)</span> <span class="token function">Speak</span><span class="token punctuation">(</span>think <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>talk <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> think <span class="token operator">==</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>sb<span class="token operator">&</span>quot<span class="token punctuation">;</span> <span class="token punctuation">{</span> talk <span class="token operator">=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>你是个大帅比<span class="token operator">&</span>quot<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> talk <span class="token operator">=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>您好<span class="token operator">&</span>quot<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> peo People <span class="token operator">=</span> Student<span class="token punctuation">{</span><span class="token punctuation">}</span> think <span class="token operator">:=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>bitch<span class="token operator">&</span>quot<span class="token punctuation">;</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>peo<span class="token punctuation">.</span><span class="token function">Speak</span><span class="token punctuation">(</span>think<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
类型与接口的关系</h1> <h1>一个类型实现多个接口</h1>

一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现。 例如,狗可以叫,也可以动。我们就分别定义Sayer接口和Mover接口,如下: <code>Mover</code>接口。

<pre><code class="lang-go hljs"><span class="token comment">// Sayer 接口</span> <span class="token keyword">type</span> Sayer <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// Mover 接口</span> <span class="token keyword">type</span> Mover <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

dog既可以实现Sayer接口,也可以实现Mover接口。

<pre><code class="lang-go hljs"><span class="token keyword">type</span> dog <span class="token keyword">struct</span> <span class="token punctuation">{</span> name <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token comment">// 实现Sayer接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d dog<span class="token punctuation">)</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token operator">%</span>s会叫汪汪汪\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> d<span class="token punctuation">.</span>name<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 实现Mover接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d dog<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token operator">%</span>s会动\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> d<span class="token punctuation">.</span>name<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x Sayer <span class="token keyword">var</span> y Mover <span class="token keyword">var</span> a <span class="token operator">=</span> dog<span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>旺财<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">}</span> x <span class="token operator">=</span> a y <span class="token operator">=</span> a x<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> y<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
多个类型实现同一接口</h1>

Go语言中不同的类型还可以实现同一接口 首先我们定义一个<code>Mover</code>接口,它要求必须由一个<code>move</code>方法。

<pre><code class="lang-go hljs"><span class="token comment">// Mover 接口</span> <span class="token keyword">type</span> Mover <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

例如狗可以动,汽车也可以动,可以使用如下代码实现这个关系:

<pre><code class="lang-go hljs"><span class="token keyword">type</span> dog <span class="token keyword">struct</span> <span class="token punctuation">{</span> name <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token keyword">type</span> car <span class="token keyword">struct</span> <span class="token punctuation">{</span> brand <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token comment">// dog类型实现Mover接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d dog<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token operator">%</span>s会跑\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> d<span class="token punctuation">.</span>name<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// car类型实现Mover接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>c car<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token operator">%</span>s速度<span class="token number">70</span>迈\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

这个时候我们在代码中就可以把狗和汽车当成一个会动的物体来处理了,不再需要关注它们具体是什么,只需要调用它们的<code>move</code>方法就可以了。

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x Mover <span class="token keyword">var</span> a <span class="token operator">=</span> dog<span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>旺财<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">var</span> b <span class="token operator">=</span> car<span class="token punctuation">{</span>brand<span class="token punctuation">:</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>保时捷<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">}</span> x <span class="token operator">=</span> a x<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> x <span class="token operator">=</span> b x<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

上面的代码执行结果如下:

<pre><code class="lang-go hljs">旺财会跑 保时捷速度<span class="token number">70</span>迈 </code></pre>

并且一个接口的方法,不一定需要由一个类型完全实现,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现。

<pre><code class="lang-go hljs"><span class="token comment">// WashingMachine 洗衣机</span> <span class="token keyword">type</span> WashingMachine <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">wash</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token function">dry</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 甩干器</span> <span class="token keyword">type</span> dryer <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 实现WashingMachine接口的dry()方法</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>d dryer<span class="token punctuation">)</span> <span class="token function">dry</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>甩一甩<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 海尔洗衣机</span> <span class="token keyword">type</span> haier <span class="token keyword">struct</span> <span class="token punctuation">{</span> dryer <span class="token comment">//嵌入甩干器</span> <span class="token punctuation">}</span> <span class="token comment">// 实现WashingMachine接口的wash()方法</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>h haier<span class="token punctuation">)</span> <span class="token function">wash</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>洗刷刷<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
接口嵌套</h1>

接口与接口间可以通过嵌套创造出新的接口。

<pre><code class="lang-go hljs"><span class="token comment">// Sayer 接口</span> <span class="token keyword">type</span> Sayer <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// Mover 接口</span> <span class="token keyword">type</span> Mover <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 接口嵌套</span> <span class="token keyword">type</span> animal <span class="token keyword">interface</span> <span class="token punctuation">{</span> Sayer Mover <span class="token punctuation">}</span> </code></pre>

嵌套得到的接口的使用与普通接口一样,这里我们让cat实现animal接口:

<pre><code class="lang-go hljs"><span class="token keyword">type</span> cat <span class="token keyword">struct</span> <span class="token punctuation">{</span> name <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>c cat<span class="token punctuation">)</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>喵喵喵<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>c cat<span class="token punctuation">)</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>猫会动<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x animal x <span class="token operator">=</span> cat<span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>花花<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">}</span> x<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> x<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
空接口</h1> <h1>空接口的定义</h1>

空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。

空接口类型的变量可以存储任意类型的变量。

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 定义一个空接口x</span> <span class="token keyword">var</span> x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> s <span class="token operator">:=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>Hello 沙河<span class="token operator">&</span>quot<span class="token punctuation">;</span> x <span class="token operator">=</span> s fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token keyword">type</span><span class="token punctuation">:</span><span class="token operator">%</span>T value<span class="token punctuation">:</span><span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> x<span class="token punctuation">,</span> x<span class="token punctuation">)</span> i <span class="token operator">:=</span> <span class="token number">100</span> x <span class="token operator">=</span> i fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token keyword">type</span><span class="token punctuation">:</span><span class="token operator">%</span>T value<span class="token punctuation">:</span><span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> x<span class="token punctuation">,</span> x<span class="token punctuation">)</span> b <span class="token operator">:=</span> <span class="token boolean">true</span> x <span class="token operator">=</span> b fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token keyword">type</span><span class="token punctuation">:</span><span class="token operator">%</span>T value<span class="token punctuation">:</span><span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> x<span class="token punctuation">,</span> x<span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
空接口的应用</h1> <h1>空接口作为函数的参数</h1>

使用空接口实现可以接收任意类型的函数参数。

<pre><code class="lang-go hljs"><span class="token comment">// 空接口作为函数参数</span> <span class="token keyword">func</span> <span class="token function">show</span><span class="token punctuation">(</span>a <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token keyword">type</span><span class="token punctuation">:</span><span class="token operator">%</span>T value<span class="token punctuation">:</span><span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> a<span class="token punctuation">,</span> a<span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <h1>
空接口作为map的值</h1>

使用空接口实现可以保存任意值的字典。

<pre><code class="lang-go hljs"><span class="token comment">// 空接口作为map值</span> <span class="token keyword">var</span> studentInfo <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> studentInfo<span class="token punctuation">[</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>name<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>沙河娜扎<span class="token operator">&</span>quot<span class="token punctuation">;</span> studentInfo<span class="token punctuation">[</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>age<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">18</span> studentInfo<span class="token punctuation">[</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>married<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">false</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>studentInfo<span class="token punctuation">)</span> </code></pre> <h1>
类型断言</h1>

空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?

<h1>
接口值</h1>

一个接口的值(简称接口值)是由<code>一个具体类型</code>和<code>具体类型的值</code>两部分组成的。这两部分分别称为接口的<code>动态类型</code>和<code>动态值</code>。

我们来看一个具体的例子:

<pre><code class="lang-go hljs"><span class="token keyword">var</span> w io<span class="token punctuation">.</span>Writer w <span class="token operator">=</span> os<span class="token punctuation">.</span>Stdout w <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>bytes<span class="token punctuation">.</span>Buffer<span class="token punctuation">)</span> w <span class="token operator">=</span> <span class="token boolean">nil</span> </code></pre>

请看下图分解:

想要判断空接口中的值这个时候就可以使用类型断言,其语法格式:

<pre><code class="lang-go hljs">x<span class="token punctuation">.</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span> </code></pre>

其中:

<ul><li>x:表示类型为<code>interface{}</code>的变量</li><li>T:表示断言<code>x</code>可能是的类型。</li></ul>

该语法返回两个参数,第一个参数是<code>x</code>转化为<code>T</code>类型后的变量,第二个值是一个布尔值,若为<code>true</code>则表示断言成功,为<code>false</code>则表示断言失败。

举个例子:

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> x <span class="token operator">=</span> <span class="token operator">&</span>quot<span class="token punctuation">;</span>Hello 沙河<span class="token operator">&</span>quot<span class="token punctuation">;</span> v<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token keyword">if</span> ok <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>类型断言失败<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre>

上面的示例中如果要断言多次就需要写多个<code>if</code>判断,这个时候我们可以使用<code>switch</code>语句来实现:

<pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">justifyType</span><span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> v <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token builtin">string</span><span class="token punctuation">:</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>x is a <span class="token builtin">string</span>,value is <span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token builtin">int</span><span class="token punctuation">:</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>x is a <span class="token builtin">int</span> is <span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token builtin">bool</span><span class="token punctuation">:</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>x is a <span class="token builtin">bool</span> is <span class="token operator">%</span>v\n<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span> <span class="token keyword">default</span><span class="token punctuation">:</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>quot<span class="token punctuation">;</span>unsupport <span class="token keyword">type</span>!<span class="token operator">&</span>quot<span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre>

因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。

关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。

到此这篇关于“Go语言基础之接口”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
想系统学习GO语言(Golang
GO语言零基础从入门到精通视频教程
go 获取函数地址_Go语言基础--接口浅析
Go语言发展历史、核心、特性及学习路线
Go语言的函数、方法和接口
Go 语言到底适合干什么?
2018年最全Go语言教程零基础入门到进阶实战视频
基于类型系统的面向对象编程语言Go
Go 语言十年而立,Go2 蓄势待发
从零开始学习GO语言-搭建Go语言开发环境-快速开发入门第一个小程序

[关闭]
~ ~