教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 谨慎对待Go语言中对interface的nil判断

谨慎对待Go语言中对interface的nil判断

发布时间:2021-12-20   编辑:jiaochengji.com
教程集为您提供谨慎对待Go语言中对interface的nil判断等资源,欢迎您收藏本站,我们将为您提供最新的谨慎对待Go语言中对interface的nil判断资源
<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><h1>谨慎对待Go语言中对interface的nil判断</h1>

在进行Go语言编程中,我们会看见诸如<code>if err == nil {}</code>或者<code>if err != nil {}</code>之类的判断,这跟go语言的错误处理哲学(计划失败而非成功 / 及早失败)有关;
大多数情况下,我们对一个<code>err</code>是否是<code>nil</code>进行判断是很直白的,无需考虑很多,但是如果对于interface的情况来说,处理的时候稍有点难度,多了许多要留意的地方。

<em>看个重要的例子</em>

<pre><code class="lang-go hljs"><span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"bytes"</span> <span class="token string">"fmt"</span> <span class="token string">"io"</span> <span class="token punctuation">)</span> <span class="token comment">//check的参数类型是io.Writer,是一个interface,所以只要某个类型的变量具有了Write方法</span> <span class="token comment">//也就等同于实现了Writer这个接口</span> <span class="token comment">//Writer的源码定义如下</span> <span class="token comment">//type Writer interface {</span> <span class="token comment">// Write(p []byte) (n int, err error)</span> <span class="token comment">//}</span> <span class="token keyword">func</span> <span class="token function">check</span><span class="token punctuation">(</span>w io<span class="token punctuation">.</span>Writer<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> w <span class="token operator">!=</span> <span class="token boolean">nil</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 string">"w不是nil"</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 string">"w是 % v\n"</span><span class="token punctuation">,</span>w<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> b <span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer <span class="token comment">//默认值是nil</span> <span class="token comment">//bytes包里面的Buffer是一个struct,它具有Write方法,也就实现了io.Writer接口</span> <span class="token comment">//从而可以作为参数</span> <span class="token comment">//func (b *Buffer) Write(p []byte) (n int, err error)</span> <span class="token function">check</span><span class="token punctuation">(</span>b<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 string">"b的值是% v\n"</span><span class="token punctuation">,</span>b<span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

大家可以先猜一下输出结果是什么?

.
.
.
.
.
.

<pre><code class="lang-go hljs">w不是<span class="token boolean">nil</span> w是 <span class="token operator"><</span><span class="token boolean">nil</span><span class="token operator">></span> b的值是<span class="token operator"><</span><span class="token boolean">nil</span><span class="token operator">></span> </code></pre>

不知道你猜对了没?但是对于新手来说,这一点确实有点困惑,w怎么一会儿是nil,一会儿又不是呢?
其实这个奇怪的现象跟go语言中interface的内部结构有关, <code>interface</code>内部由一个类型<code>T</code>和一个值<code>V</code>构成,其中V是一个具体类型(int, struct, pointer,string…)的值,比如int类型的<code>10</code>或者string类型的<code>“wdy”</code>

PS: 前天我发了一篇名为《如何理解Go语言的空接口interface{}》,对interface内部不懂的同学请看回头翻一下那篇文章

<h3>
重点来了</h3> <blockquote> <h2>一个interface要想为nil,只有可能是它内部的 T 和 V 都为nil.</h2> </blockquote>

阅读下面代码的前提【知识储备-源码】

<pre><code class="lang-go hljs"><span class="token comment">//我们知道error是一个类型,同时在go语言的源码定义中,error也是一个interface</span> <span class="token keyword">type</span> <span class="token builtin">error</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token function">Error</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 comment">//所以任意一个类型拥有了方法 func (any <any Type>) Error() string {}就是实现了error这个interface</span> <span class="token comment">//比如:</span> <span class="token keyword">type</span> some <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>s <span class="token operator">*</span>some<span class="token punctuation">)</span> <span class="token function">Error</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 string">"some"</span> <span class="token punctuation">}</span> <span class="token comment">//这个代码段说明*some这个类型实现了error这个interface</span> </code></pre> <pre><code class="lang-go hljs"><span class="token keyword">package</span> main <span class="token keyword">import</span><span class="token punctuation">(</span> <span class="token string">"fmt"</span> <span class="token punctuation">)</span> <span class="token keyword">type</span> someError <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">//类型定义</span> <span class="token comment">//*someError这个类型通过定义Error()函数实现了error这个接口</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>se <span class="token operator">*</span>someError<span class="token punctuation">)</span> <span class="token function">Error</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 string">"wdy"</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">check</span><span class="token punctuation">(</span>e <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> e <span class="token operator">!=</span> <span class="token boolean">nil</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 string">"e 不是nil"</span><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 string">"e 是 nil"</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 string">"e的值是% v\n"</span><span class="token punctuation">,</span>e<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 comment">//情况1</span> <span class="token keyword">var</span> e <span class="token builtin">error</span> <span class="token operator">=</span> <span class="token boolean">nil</span> <span class="token function">check</span><span class="token punctuation">(</span>e<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 punctuation">)</span> <span class="token comment">//情况2</span> <span class="token keyword">var</span> se <span class="token operator">*</span>someError <span class="token operator">=</span> <span class="token boolean">nil</span> <span class="token function">check</span><span class="token punctuation">(</span>se<span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre>

同样请猜一下输出结果:

.
.
.
.
.
.

<pre><code class="lang-go hljs">e 是 <span class="token boolean">nil</span> e的值是<span class="token operator"><</span><span class="token boolean">nil</span><span class="token operator">></span> e 不是<span class="token boolean">nil</span> e的值是wdy </code></pre>

记得实操一遍哦,自己在Go playground上面动手,尝试自己写一个例子。
<code>【weixin-公-众-号:go学习】</code>

到此这篇关于“谨慎对待Go语言中对interface的nil判断”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
谨慎对待Go语言中对interface的nil判断
golang 面试题(十三)interface内部结构和nil详解
Golang interface(接口)的nil判断
go 语言学习历程
Go接口之nil != nil
go 函数末尾缺少返回值_王垠:Go语言野心勃勃,实际情况又如何
Go语言接口interface
14. Go 语言中的类型断言是什么?
go语言有哪些优势?Go语言的核心特性有哪些
Go 语言的核心优势

[关闭]
~ ~