<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Error | 酷 壳 - CoolShell</title>
	<atom:link href="https://coolshell.cn/tag/error/feed" rel="self" type="application/rss+xml" />
	<link>https://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - Coding Your Ambition</description>
	<lastBuildDate>Mon, 28 Dec 2020 04:26:53 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>Go 编程模式：错误处理</title>
		<link>https://coolshell.cn/articles/21140.html</link>
					<comments>https://coolshell.cn/articles/21140.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Tue, 22 Dec 2020 10:19:30 +0000</pubDate>
				<category><![CDATA[Go 语言]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[golang]]></category>
		<guid isPermaLink="false">https://coolshell.cn/?p=21140</guid>

					<description><![CDATA[<p>错误处理一直以一是编程必需要面对的问题，错误处理如果做的好的话，代码的稳定性会很好。不同的语言有不同的出现处理的方式。Go语言也一样，在本篇文章中，我们来讨论一...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/21140.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/21140.html">Go 编程模式：错误处理</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script><img decoding="async" loading="lazy" class="alignright size-medium wp-image-21143" src="https://coolshell.cn/wp-content/uploads/2020/12/err-check-300x186.jpg" alt="" width="300" height="186" srcset="https://coolshell.cn/wp-content/uploads/2020/12/err-check-300x186.jpg 300w, https://coolshell.cn/wp-content/uploads/2020/12/err-check-768x477.jpg 768w, https://coolshell.cn/wp-content/uploads/2020/12/err-check-435x270.jpg 435w, https://coolshell.cn/wp-content/uploads/2020/12/err-check.jpg 770w" sizes="(max-width: 300px) 100vw, 300px" />错误处理一直以一是编程必需要面对的问题，错误处理如果做的好的话，代码的稳定性会很好。不同的语言有不同的出现处理的方式。Go语言也一样，在本篇文章中，我们来讨论一下Go语言的出错出处，尤其是那令人抓狂的 <code>if err != nil</code> 。</p>
<p>在正式讨论Go代码里满屏的 <code>if err != nil</code> 怎么办这个事之前，我想先说一说编程中的错误处理。这样可以让大家在更高的层面理解编程中的错误处理。</p>
<section class="post-series"><h3 class="post-series-title">本文是全系列中第2 / 10篇：<a href="https://coolshell.cn/articles/series/go%e7%bc%96%e7%a8%8b%e6%a8%a1%e5%bc%8f">Go编程模式</a></h3><ul class="post-series-list"><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21128.html">Go编程模式：切片，接口，时间和性能</a></span></li><li class="post-series-item-current post-series-item"><span class="post-series-item-title">Go 编程模式：错误处理</span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21146.html">Go 编程模式：Functional Options</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21214.html">Go编程模式：委托和反转控制</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21164.html">Go编程模式：Map-Reduce</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21179.html">Go 编程模式：Go Generation</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/17929.html">Go编程模式：修饰器</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21228.html">Go编程模式：Pipeline</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21263.html">Go 编程模式：k8s Visitor 模式</a></span></li><li class="post-series-item"><span class="post-series-item-title"><a href="https://coolshell.cn/articles/21615.html">Go编程模式 ： 泛型编程</a></span></li></ul><nav class="post-series-nav"><span class="post-series-nav-prev">&laquo; <a href="https://coolshell.cn/articles/21128.html" rel="prev" title="Go编程模式：切片，接口，时间和性能">上一篇文章</a></span><span class="post-series-nav-next"><a href="https://coolshell.cn/articles/21146.html" rel="next" title="Go 编程模式：Functional Options">下一篇文章</a> &raquo;</span></nav></section>
<h4>C语言的错误检查</h4>
<p>首先，我们知道，处理错误最直接的方式是通过错误码，这也是传统的方式，在过程式语言中通常都是用这样的方式处理错误的。比如 C 语言，基本上来说，其通过函数的返回值标识是否有错，然后通过全局的 <code>errno</code> 变量并配合一个 <code>errstr</code> 的数组来告诉你为什么出错。</p>
<p>为什么是这样的设计？道理很简单，除了可以共用一些错误，更重要的是这其实是一种妥协。比如：<code>read()</code>, <code>write()</code>, <code>open()</code> 这些函数的返回值其实是返回有业务逻辑的值。也就是说，这些函数的返回值有两种语义，一种是成功的值，比如 <code>open()</code> 返回的文件句柄指针 <code>FILE*</code> ，或是错误 <code>NULL</code>。这样会导致调用者并不知道是什么原因出错了，需要去检查 <code>errno</code> 来获得出错的原因，从而可以正确地处理错误。</p>
<p>一般而言，这样的错误处理方式在大多数情况下是没什么问题的。但是也有例外的情况，我们来看一下下面这个 C 语言的函数：</p>
<p><span id="more-21140"></span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">int atoi(const char *str)</pre>
<p>这个函数是把一个字符串转成整型。但是问题来了，如果一个要传的字符串是非法的（不是数字的格式），如 &#8220;ABC&#8221; 或者整型溢出了，那么这个函数应该返回什么呢？出错返回，返回什么数都不合理，因为这会和正常的结果混淆在一起。比如，返回 <code>0</code>，那么会和正常的对 “0” 字符的返回值完全混淆在一起。这样就无法判断出错的情况。你可能会说，是不是要检查一下 <code>errno</code>，按道理说应该是要去检查的，但是，我们在 C99 的规格说明书中可以看到这样的描述——</p>
<blockquote><p>7.20.1The functions atof, atoi, atol, and atoll need not affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undeﬁned.</p></blockquote>
<p>像<code>atoi()</code>, <code>atof()</code>, <code>atol()</code> 或是 <code>atoll()</code> 这样的函数是不会设置 <code>errno</code>的，而且，还说了，如果结果无法计算的话，行为是undefined。所以，后来，libc 又给出了一个新的函数<code>strtol()</code>，这个函数在出错的时会设置全局变量 <code>errno</code> ：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">long val = strtol(in_str, &amp;endptr, 10);  //10的意思是10进制

//如果无法转换
if (endptr == str) {
    fprintf(stderr, "No digits were found\n");
    exit(EXIT_FAILURE);
}

//如果整型溢出了
if ((errno == ERANGE &amp;&amp; (val == LONG_MAX || val == LONG_MIN)) {
    fprintf(stderr, "ERROR: number out of range for LONG\n");
    exit(EXIT_FAILURE);
 }

//如果是其它错误
if (errno != 0 &amp;&amp; val == 0) {
    perror("strtol");
    exit(EXIT_FAILURE);
}
</pre>
<p>虽然，<code>strtol()</code> 函数解决了 <code>atoi()</code> 函数的问题，但是我们还是能感觉到不是很舒服和自然。</p>
<p>因为，这种用 返回值 + errno 的错误检查方式会有一些问题:</p>
<ul>
<li>程序员一不小心就会忘记返回值的检查，从而造成代码的 Bug；</li>
<li>函数接口非常不纯洁，正常值和错误值混淆在一起，导致语义有问题。</li>
</ul>
<p>所以，后来，有一些类库就开始区分这样的事情。比如，Windows 的系统调用开始使用 <code>HRESULT</code> 的返回来统一错误的返回值，这样可以明确函数调用时的返回值是成功还是错误。但这样一来，函数的 input 和 output 只能通过函数的参数来完成，于是出现了所谓的 入参 和 出参 这样的区别。</p>
<p>然而，这又使得函数接入中参数的语义变得复杂，一些参数是入参，一些参数是出参，函数接口变得复杂了一些。而且，依然没有解决函数的成功或失败可以被人为忽略的问题。</p>
<h4>Java的错误处理</h4>
<p>Java语言使用 <code>try-catch-finally</code> 通过使用异常的方式来处理错误，其实，这比起C语言的错处理进了一大步，使用抛异常和抓异常的方式可以让我们的代码有这样的一些好处：</p>
<ul>
<li>函数接口在 input（参数）和 output（返回值）以及错误处理的语义是比较清楚的。</li>
<li>正常逻辑的代码可以与错误处理和资源清理的代码分开，提高了代码的可读性。</li>
<li>异常不能被忽略（如果要忽略也需要 catch 住，这是显式忽略）。</li>
<li>在面向对象的语言中（如 Java），异常是个对象，所以，可以实现多态式的 catch。</li>
<li>与状态返回码相比，异常捕捉有一个显著的好处是，函数可以嵌套调用，或是链式调用。比如：
<ul>
<li><code>int x = add(a, div(b,c));</code></li>
<li><code>Pizza p = PizzaBuilder().SetSize(sz).SetPrice(p)...;</code></li>
</ul>
</li>
</ul>
<h4>Go语言的错误处理</h4>
<p>Go 语言的函数支持多返回值，所以，可以在返回接口把业务语义（业务返回值）和控制语义（出错返回值）区分开来。Go 语言的很多函数都会返回 result, err 两个值，于是:</p>
<ul>
<li>参数上基本上就是入参，而返回接口把结果和错误分离，这样使得函数的接口语义清晰；</li>
<li>而且，Go 语言中的错误参数如果要忽略，需要显式地忽略，用 _ 这样的变量来忽略；</li>
<li>另外，因为返回的 <code>error</code> 是个接口（其中只有一个方法 <code>Error()</code>，返回一个 <code>string</code> ），所以你可以扩展自定义的错误处理。</li>
</ul>
<p>另外，如果一个函数返回了多个不同类型的 <code>error</code>，你也可以使用下面这样的方式：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">if err != nil {
  switch err.(type) {
    case *json.SyntaxError:
      ...
    case *ZeroDivisionError:
      ...
    case *NullPointerError:
      ...
    default:
      ...
  }
}</pre>
<p>我们可以看到，Go语言的错误处理的的方式，本质上是返回值检查，但是他也兼顾了异常的一些好处 &#8211; 对错误的扩展。</p>
<h4>资源清理</h4>
<p>出错后是需要做资源清理的，不同的编程语言有不同的资源清理的编程模式：</p>
<ul>
<li>C语言 &#8211; 使用的是 <code>goto fail;</code> 的方式到一个集中的地方进行清理（有篇有意思的文章可以看一下《<a title="由苹果的低级Bug想到的" href="https://coolshell.cn/articles/11112.html" target="_blank" rel="noopener">由苹果的低级BUG想到的</a>》）</li>
<li>C++语言- 一般来说使用 <a href="https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization" target="_blank" rel="noopener">RAII模式</a>，通过面向对象的代理模式，把需要清理的资源交给一个代理类，然后在析构函数来解决。</li>
<li>Java语言 &#8211; 可以在finally 语句块里进行清理。</li>
<li>Go语言 &#8211; 使用 <code>defer</code> 关键词进行清理。</li>
</ul>
<p>下面是一个Go语言的资源清理的示例：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">func Close(c io.Closer) {
  err := c.Close()
  if err != nil {
    log.Fatal(err)
  }
}

func main() {
  r, err := Open("a")
  if err != nil {
    log.Fatalf("error opening 'a'\n")
  }
  defer Close(r) // 使用defer关键字在函数退出时关闭文件。

  r, err = Open("b")
  if err != nil {
    log.Fatalf("error opening 'b'\n")
  }
  defer Close(r) // 使用defer关键字在函数退出时关闭文件。
}</pre>
<h4>Error Check  Hell</h4>
<p>好了，说到 Go 语言的 <code>if err !=nil</code> 的代码了，这样的代码的确是能让人写到吐。那么有没有什么好的方式呢，有的。我们先看如下的一个令人崩溃的代码。</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">func parse(r io.Reader) (*Point, error) {

    var p Point

    if err := binary.Read(r, binary.BigEndian, &amp;p.Longitude); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &amp;p.Latitude); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &amp;p.Distance); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &amp;p.ElevationGain); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &amp;p.ElevationLoss); err != nil {
        return nil, err
    }
}</pre>
<p>要解决这个事，我们可以用函数式编程的方式，如下代码示例：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">func parse(r io.Reader) (*Point, error) {
    var p Point
    var err error
    read := func(data interface{}) {
        if err != nil {
            return
        }
        err = binary.Read(r, binary.BigEndian, data)
    }

    read(&amp;p.Longitude)
    read(&amp;p.Latitude)
    read(&amp;p.Distance)
    read(&amp;p.ElevationGain)
    read(&amp;p.ElevationLoss)

    if err != nil {
        return &amp;p, err
    }
    return &amp;p, nil
}</pre>
<p>上面的代码我们可以看到，我们通过使用Closure 的方式把相同的代码给抽出来重新定义一个函数，这样大量的  <code>if err!=nil</code> 处理的很干净了。但是会带来一个问题，那就是有一个 <code>err</code> 变量和一个内部的函数，感觉不是很干净。</p>
<p>那么，我们还能不能搞得更干净一点呢，我们从Go 语言的 <code>bufio.Scanner()</code>中似乎可以学习到一些东西：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">scanner := bufio.NewScanner(input)

for scanner.Scan() {
    token := scanner.Text()
    // process token
}

if err := scanner.Err(); err != nil {
    // process the error
}</pre>
<p>上面的代码我们可以看到，<code>scanner</code>在操作底层的I/O的时候，那个for-loop中没有任何的 <code>if err !=nil</code> 的情况，退出循环后有一个 <code>scanner.Err()</code> 的检查。看来使用了结构体的方式。模仿它，我们可以把我们的代码重构成下面这样：</p>
<p>首先，定义一个结构体和一个成员函数</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">type Reader struct {
    r   io.Reader
    err error
}

func (r *Reader) read(data interface{}) {
    if r.err == nil {
        r.err = binary.Read(r.r, binary.BigEndian, data)
    }
}</pre>
<p>然后，我们的代码就可以变成下面这样：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">func parse(input io.Reader) (*Point, error) {
    var p Point
    r := Reader{r: input}

    r.read(&amp;p.Longitude)
    r.read(&amp;p.Latitude)
    r.read(&amp;p.Distance)
    r.read(&amp;p.ElevationGain)
    r.read(&amp;p.ElevationLoss)

    if r.err != nil {
        return nil, r.err
    }

    return &amp;p, nil
}</pre>
<p>有了上面这个技术，我们的“<a href="https://martinfowler.com/bliki/FluentInterface.html" target="_blank" rel="noopener">流式接口 Fluent Interface</a>”，也就很容易处理了。如下所示：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">package main

import (
  "bytes"
  "encoding/binary"
  "fmt"
)

// 长度不够，少一个Weight
var b = []byte {0x48, 0x61, 0x6f, 0x20, 0x43, 0x68, 0x65, 0x6e, 0x00, 0x00, 0x2c} 
var r = bytes.NewReader(b)

type Person struct {
  Name [10]byte
  Age uint8
  Weight uint8
  err error
}
func (p *Person) read(data interface{}) {
  if p.err == nil {
    p.err = binary.Read(r, binary.BigEndian, data)
  }
}

func (p *Person) ReadName() *Person {
  p.read(&amp;p.Name) 
  return p
}
func (p *Person) ReadAge() *Person {
  p.read(&amp;p.Age) 
  return p
}
func (p *Person) ReadWeight() *Person {
  p.read(&amp;p.Weight) 
  return p
}
func (p *Person) Print() *Person {
  if p.err == nil {
    fmt.Printf("Name=%s, Age=%d, Weight=%d\n",p.Name, p.Age, p.Weight)
  }
  return p
}

func main() {   
  p := Person{}
  p.ReadName().ReadAge().ReadWeight().Print()
  fmt.Println(p.err)  // EOF 错误
}
</pre>
<p>相信你应该看懂这个技巧了，但是，其使用场景也就只能在对于同一个业务对象的不断操作下可以简化错误处理，对于多个业务对象的话，还是得需要各种 <code>if err != nil</code>的方式。</p>
<h4>包装错误</h4>
<p>最后，多说一句，我们需要包装一下错误，而不是干巴巴地把<code>err</code>给返回到上层，我们需要把一些执行的上下文加入。</p>
<p>通常来说，我们会使用 <code>fmt.Errorf()</code>来完成这个事，比如：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">if err != nil {
   return fmt.Errorf("something failed: %v", err)
}</pre>
<p>另外，在Go语言的开发者中，更为普遍的做法是将错误包装在另一个错误中，同时保留原始内容：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">type authorizationError struct {
    operation string
    err error   // original error
}

func (e *authorizationError) Error() string {
    return fmt.Sprintf("authorization failed during %s: %v", e.operation, e.err)
}</pre>
<p>当然，更好的方式是通过一种标准的访问方法，这样，我们最好使用一个接口，比如 <code>causer</code>接口中实现 <code>Cause()</code> 方法来暴露原始错误，以供进一步检查：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">type causer interface {
    Cause() error
}

func (e *authorizationError) Cause() error {
    return e.err
}
</pre>
<p>&nbsp;</p>
<p>这里有个好消息是，这样的代码不必再写了，有一个第三方的错误库（<a href="https://github.com/pkg/errors" target="_blank" rel="noopener">github.com/pkg/errors</a>），对于这个库，我无论到哪都能看到他的存在，所以，这个基本上来说就是事实上的标准了。代码示例如下：</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">import "github.com/pkg/errors"

//错误包装
if err != nil {
    return errors.Wrap(err, "read failed")
}

// Cause接口
switch err := errors.Cause(err).(type) {
case *MyError:
    // handle specifically
default:
    // unknown error
}</pre>
<h4>参考文章</h4>
<ul>
<li><b>Golang Error Handling lesson by Rob Pike<br />
</b><a href="http://jxck.hatenablog.com/entry/golang-error-handling-lesson-by-rob-pike">http://jxck.hatenablog.com/entry/golang-error-handling-lesson-by-rob-pike</a></li>
<li><b>Errors are values<br />
</b><a href="https://blog.golang.org/errors-are-values">https://blog.golang.org/errors-are-values</a></li>
</ul>
<p>（全文完）<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/21615.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2021/09/go-generics-150x150.png" alt="Go编程模式 ： 泛型编程" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21615.html" class="wp_rp_title">Go编程模式 ： 泛型编程</a></li><li ><a href="https://coolshell.cn/articles/21263.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/12/go.k8s-150x150.png" alt="Go 编程模式：k8s Visitor 模式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21263.html" class="wp_rp_title">Go 编程模式：k8s Visitor 模式</a></li><li ><a href="https://coolshell.cn/articles/21228.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/12/go.line_.-150x150.png" alt="Go编程模式：Pipeline" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21228.html" class="wp_rp_title">Go编程模式：Pipeline</a></li><li ><a href="https://coolshell.cn/articles/21214.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/12/go.pair_-150x150.png" alt="Go编程模式：委托和反转控制" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21214.html" class="wp_rp_title">Go编程模式：委托和反转控制</a></li><li ><a href="https://coolshell.cn/articles/21179.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/12/go.generate-150x150.png" alt="Go 编程模式：Go Generation" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21179.html" class="wp_rp_title">Go 编程模式：Go Generation</a></li><li ><a href="https://coolshell.cn/articles/21164.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/12/go.map_.reduce-150x150.png" alt="Go编程模式：Map-Reduce" width="150" height="150" /></a><a href="https://coolshell.cn/articles/21164.html" class="wp_rp_title">Go编程模式：Map-Reduce</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/21140.html">Go 编程模式：错误处理</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/21140.html/feed</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
			</item>
		<item>
		<title>10大经典错误</title>
		<link>https://coolshell.cn/articles/5107.html</link>
					<comments>https://coolshell.cn/articles/5107.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Mon, 08 Aug 2011 00:37:36 +0000</pubDate>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[轶事趣闻]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=5107</guid>

					<description><![CDATA[<p>下面是10、11个经典的错误，升序排名。希望大家补充！ 10、DOS的Abort，Retry, Fail？错误 85年以后出生的人可能不知道DOS是什么了，只有...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/5107.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/5107.html">10大经典错误</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script>下面是10、11个经典的错误，升序排名。希望大家补充！</p>
<h4>10、DOS的Abort，Retry, Fail？错误</h4>
<p>85年以后出生的人可能不知道DOS是什么了，只有那老家伙还知道这是什么。我还记得当时的我对于Abort和Fail这两个选择还是比较清楚的，不过，今天完全忘记了Abort和Fail的差别是什么？这个出是DOS下的经常出现，也相当的经典，以至于在Wikepedia上都有专门的业面 <a href="http://en.wikipedia.org/wiki/Abort,_Retry,_Fail%3F" target="_blank">Abort, Retry, Fail?</a>。简称为ARF。当然，ARI &#8211; Abort, Retry, Ignore?</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-5108" title="Dos Abort Retry Fail" src="https://coolshell.cn/wp-content/uploads/2011/08/Dos_Abort_Retry_Fail.png" alt="" width="220" height="112" /></p>
<h4>9、Windows Vista 的红屏错误</h4>
<p><a href="http://en.wikipedia.org/wiki/Red_Screen_of_Death" target="_blank">红屏错误</a>（RSoD &#8211; Red Screen of Death）不单单只是Windows Vista引入的（也许是蓝屏太有名了，突然变成红屏，大家觉得这个是比蓝屏更NB的错，所以也就引人关注了），PlayStation的也喜欢使用红屏。</p>
<figure id="attachment_5109" aria-describedby="caption-attachment-5109" style="width: 512px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5109  " title="Longhorn RSoD" src="https://coolshell.cn/wp-content/uploads/2011/08/Longhorn_RSoD.png" alt="" width="512" height="320" srcset="https://coolshell.cn/wp-content/uploads/2011/08/Longhorn_RSoD.png 640w, https://coolshell.cn/wp-content/uploads/2011/08/Longhorn_RSoD-300x187.png 300w" sizes="(max-width: 512px) 100vw, 512px" /><figcaption id="caption-attachment-5109" class="wp-caption-text">Windows Vista 的 RSoD</figcaption></figure>
<p><span id="more-5107"></span></p>
<figure id="attachment_5110" aria-describedby="caption-attachment-5110" style="width: 480px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5110" title="PSP的红屏" src="https://coolshell.cn/wp-content/uploads/2011/08/Rsodhc6.png" alt="" width="480" height="272" srcset="https://coolshell.cn/wp-content/uploads/2011/08/Rsodhc6.png 480w, https://coolshell.cn/wp-content/uploads/2011/08/Rsodhc6-300x170.png 300w" sizes="(max-width: 480px) 100vw, 480px" /><figcaption id="caption-attachment-5110" class="wp-caption-text">PSP的红屏</figcaption></figure>
<h4>8、PC机的开机报警</h4>
<p>攒过PC的朋友都知道如果你的内存条有问题，PC开机时会长鸣报警，一长一短则是显卡有问题，等等。你可以上Wikipedia上看看相关的词条——<a href="http://en.wikipedia.org/wiki/Power-on_self_test">Power On Self-Test Beep</a>。</p>
<figure id="attachment_5111" aria-describedby="caption-attachment-5111" style="width: 400px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5111" title="AMI BIOS " src="https://coolshell.cn/wp-content/uploads/2011/08/POST_P5KPL.jpg" alt="" width="400" height="317" srcset="https://coolshell.cn/wp-content/uploads/2011/08/POST_P5KPL.jpg 400w, https://coolshell.cn/wp-content/uploads/2011/08/POST_P5KPL-300x237.jpg 300w" sizes="(max-width: 400px) 100vw, 400px" /><figcaption id="caption-attachment-5111" class="wp-caption-text">第一代的AMI BIOS</figcaption></figure>
<h4>7、Twitter的大鲸鱼</h4>
<p>Twitter的服务器负载一吃紧，下面的这个页面就会显现出来了，大家把它叫做<strong>Fail Whale </strong>，这个情况在今年4月份以前的2到3年是非常频繁发生的，现在看似好很多了，看来Twitter工程师们克服了这个负载问题。你千万不要以为这个图是Twitter自己设计的，这个图是一个叫<a href="http://www.google.com/search?q=yiying+lu&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=FlockInc.:en-US:unofficial&amp;client=firefox">Yiying Lu</a>的人设计的。不过由Twitter引发出来的文化影响力是比较深远的，甚至还出现了相要把这个事发扬光大的Fail Whale project (<a href="http://www.twitter.com/failwhale">@FailWhale</a>, <a href="http://www.failwhale.com/">failwhale.com</a>)以及相关的T恤衫。你可以看看<a href="http://www.readwriteweb.com/archives/the_story_of_the_fail_whale.php" target="_blank">这篇文章</a>。</p>
<figure id="attachment_5112" aria-describedby="caption-attachment-5112" style="width: 511px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5112 " title="Twitter Fail Whale" src="https://coolshell.cn/wp-content/uploads/2011/08/FailWhale.png" alt="" width="511" height="375" srcset="https://coolshell.cn/wp-content/uploads/2011/08/FailWhale.png 639w, https://coolshell.cn/wp-content/uploads/2011/08/FailWhale-300x220.png 300w" sizes="(max-width: 511px) 100vw, 511px" /><figcaption id="caption-attachment-5112" class="wp-caption-text">Twitter Fail Whale</figcaption></figure>
<h4>6、Kernel Panic</h4>
<p>Kernel Panic相关于Windows 的蓝屏错误，其发生在Mac OS X和Linux下，在Mac OS X v10.6 <em>Snow Leopard</em>中，当进入内核错误后，会在画面上出现一个有英语、法语、德语、西班牙语及日语的当机画面，被多数用户称为“五国语言当机”，简称“五国”。在Linux上则是Linux Kernel oops。当内核检测到问题时，它会打印一个oops信息然后杀死全部相关进程。oops信息可以帮助Linux内核工程师调试，检测oops出现的条件，并修复导致oops的程序错误。</p>
<figure id="attachment_5113" aria-describedby="caption-attachment-5113" style="width: 460px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5113" title="Mac OS X 10.6的内核错误警告，俗称“五国”" src="https://coolshell.cn/wp-content/uploads/2011/08/Panic10.6.png" alt="" width="460" height="285" srcset="https://coolshell.cn/wp-content/uploads/2011/08/Panic10.6.png 460w, https://coolshell.cn/wp-content/uploads/2011/08/Panic10.6-300x185.png 300w" sizes="(max-width: 460px) 100vw, 460px" /><figcaption id="caption-attachment-5113" class="wp-caption-text">Mac OS X 10.6的内核错误警告，俗称“五国”</figcaption></figure>
<figure id="attachment_5114" aria-describedby="caption-attachment-5114" style="width: 480px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5114 " title="Linux-2.6-oops-parisc" src="https://coolshell.cn/wp-content/uploads/2011/08/Linux-2.6-oops-parisc.jpg" alt="" width="480" height="480" srcset="https://coolshell.cn/wp-content/uploads/2011/08/Linux-2.6-oops-parisc.jpg 600w, https://coolshell.cn/wp-content/uploads/2011/08/Linux-2.6-oops-parisc-150x150.jpg 150w, https://coolshell.cn/wp-content/uploads/2011/08/Linux-2.6-oops-parisc-300x300.jpg 300w" sizes="(max-width: 480px) 100vw, 480px" /><figcaption id="caption-attachment-5114" class="wp-caption-text">PA-RISC上发生的Linux内核oops，用ASCII显示一头死牛</figcaption></figure>
<h4>5、Windows的非法操作</h4>
<p>这个错误信息主要是操作系统用来保护自己的错误，也就是Windows下的程序crash。通常来说，是内存访问错误引发的。不过，这个东西在windows下太多了，这是Win95和Win98中的大量的问题，包括微软自己的软件也经常出现这个问题，最为典型的就是IE6的crash。让IE6 出现这样的错误真是太简单了，参看<a title="一个jQuery的插件" href="https://coolshell.cn/articles/2357.html" target="_blank">酷壳的这篇文章</a>。</p>
<figure id="attachment_5115" aria-describedby="caption-attachment-5115" style="width: 398px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5115" title="该程序执行了非法操作" src="https://coolshell.cn/wp-content/uploads/2011/08/gag_screenshot.gif" alt="" width="398" height="135" srcset="https://coolshell.cn/wp-content/uploads/2011/08/gag_screenshot.gif 398w, https://coolshell.cn/wp-content/uploads/2011/08/gag_screenshot-300x101.gif 300w" sizes="(max-width: 398px) 100vw, 398px" /><figcaption id="caption-attachment-5115" class="wp-caption-text">该程序执行了非法操作</figcaption></figure>
<h4>4、Windows RPC Error</h4>
<p>这个错误之所以很牛，是因为在2003年的8月份，很多使用Windows的用户都看到了这个错误，其系统被强行重启，重启了以后又收到这个错误，然后又被重启。这个事看上去就像一个正常的Windows的错误（相当正常，因为这样的红叉叉在Windows上看到了N多次了，用户都习惯了），但其实，这个事是有人故意的，这就是那个著名的<a href="http://en.wikipedia.org/wiki/Blaster_(computer_worm)">Blaster worm</a>蠕虫病毒，其利用了Windows DCOM的一个漏洞。</p>
<figure id="attachment_5116" aria-describedby="caption-attachment-5116" style="width: 282px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5116" title="Windows RPC Error" src="https://coolshell.cn/wp-content/uploads/2011/08/Windows-RPC-Error.jpg" alt="" width="282" height="258" /><figcaption id="caption-attachment-5116" class="wp-caption-text">Windows RPC Error</figcaption></figure>
<h4>3、Xbox 360 三红错误</h4>
<p>这个错误又叫RRoD &#8211; Red Ring of Death，在中国地区叫“三红”。微软在推出的游戏主机Xbox360后，众多用户曾向微软方面投诉游戏主机经常出现不同程度的故障，而且概率偏高，有调查显示，早期版本Xbox360返修率高达68% ，而最近的报告指出故障机率还是有33%。过热是游戏配件产品制造商Nyko认为Xbox360主机发生三红灯警告的主要原因，也有人指出因为Xbox 360机能不足所以长期开机超频引致过热。<a href="http://www.bloomberg.com/apps/news?pid=newsarchive&amp;sid=aOrvYZ2gPwZk&amp;refer=home" target="_blank">有报告指出</a>微软花费了超过11.5亿美元在回收及修理出现问题的XBOX 360。</p>
<figure id="attachment_5118" aria-describedby="caption-attachment-5118" style="width: 455px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5118" title="XBox 360 Red Ring of Death" src="https://coolshell.cn/wp-content/uploads/2011/08/XBox-Red-Ring-of-Death.jpg" alt="" width="455" height="341" srcset="https://coolshell.cn/wp-content/uploads/2011/08/XBox-Red-Ring-of-Death.jpg 455w, https://coolshell.cn/wp-content/uploads/2011/08/XBox-Red-Ring-of-Death-300x224.jpg 300w" sizes="(max-width: 455px) 100vw, 455px" /><figcaption id="caption-attachment-5118" class="wp-caption-text">XBox 360 Red Ring of Death</figcaption></figure>
<h4 style="text-align: left;">2、Web上的404错误</h4>
<p style="text-align: left;">HTTP 404或Not Found错误讯息是HTTP的其中一种“标准回应讯息”（HTTP状态码），此讯息代表客户端在浏览网页时，服务器无法打到用户要请求的资源，所以报错。404是一个你无法避免的错误，因为可能是因为用户或你的开发人员编码里打错连接。所以，很多公司借用这个机会来美化404页面，本站以前也介绍过（如：<a title="StackOverflow的404错误页" href="https://coolshell.cn/articles/2529.html" target="_blank">StackOverflow的404</a>，<a title="几个有趣的404错误页面" href="https://coolshell.cn/articles/1826.html" target="_blank">各式各样的404错</a>），这里还有一个404的一首诗：</p>
<blockquote>
<p style="text-align: left;">four oh four<br />
by mind21_98</p>
<p>oh what a wonderful tizzy<br />
which was in a fizzy<br />
he couldn&#8217;t find the file<br />
which was hiding in the bushes</p>
<p>push the back button oh traveller<br />
contact the owner of the last tavern<br />
find out how to get to where you&#8217;re going<br />
and be on your way</p></blockquote>
<h4 style="text-align: left;">1、Windows 蓝屏错误</h4>
<p style="text-align: left;"><a href="http://en.wikipedia.org/wiki/Blue_Screen_of_Death" target="_blank">Blue Screen of Death</a>，缩写为：<strong>BSoD</strong>。这是这个世界最著名的错误了，和Kernel Panic 一样，基本上就是说，内核死翘翘了。在各种场合上我们都能看到这个错误。</p>
<figure id="attachment_5119" aria-describedby="caption-attachment-5119" style="width: 535px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5119" title="北京2008奥林匹克" src="https://coolshell.cn/wp-content/uploads/2011/08/bjolympics.png" alt="" width="535" height="368" srcset="https://coolshell.cn/wp-content/uploads/2011/08/bjolympics.png 535w, https://coolshell.cn/wp-content/uploads/2011/08/bjolympics-300x206.png 300w" sizes="(max-width: 535px) 100vw, 535px" /><figcaption id="caption-attachment-5119" class="wp-caption-text">北京2008奥林匹克</figcaption></figure>
<figure id="attachment_5120" aria-describedby="caption-attachment-5120" style="width: 535px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5120" title="飞机场航班显示" src="https://coolshell.cn/wp-content/uploads/2011/08/bsodairport.png" alt="" width="535" height="400" srcset="https://coolshell.cn/wp-content/uploads/2011/08/bsodairport.png 535w, https://coolshell.cn/wp-content/uploads/2011/08/bsodairport-300x224.png 300w" sizes="(max-width: 535px) 100vw, 535px" /><figcaption id="caption-attachment-5120" class="wp-caption-text">飞机场航班显示</figcaption></figure>
<figure id="attachment_5121" aria-describedby="caption-attachment-5121" style="width: 535px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5121" title="商场显示屏" src="https://coolshell.cn/wp-content/uploads/2011/08/bsodbay.png" alt="" width="535" height="359" srcset="https://coolshell.cn/wp-content/uploads/2011/08/bsodbay.png 535w, https://coolshell.cn/wp-content/uploads/2011/08/bsodbay-300x201.png 300w" sizes="(max-width: 535px) 100vw, 535px" /><figcaption id="caption-attachment-5121" class="wp-caption-text">商场显示屏</figcaption></figure>
<p>Bill Gates在Win98发布会上的蓝屏遭遇：</p>
<p><center><embed src="http://www.tudou.com/v/eISuBfkMxlo/v.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="480" height="400"></embed></center></p>
<p>&nbsp;</p>
<p>本来文章到这里就可以结束了，上文参考自这里<a href="http://technologizer.com/2008/09/18/errormessage" target="_blank">The 13 Greatest Error Message of All Time</a>。不过，我觉得还有一个错误必然会载入史册。这就是下面的“该页无法显示错误”</p>
<h4>0、该页无法显示错误</h4>
<p>这个错误对于中国用户不会陌生。这个错误以前更多的是Connection Reset，N年前你访问很多国外的网站者会遇到Connection Reset错，今天呢，更多的是“Time Out”，因为，关键词匹配太耗性能了，图片和视频的无法使用关键词过滤，所以，还不如直接封了IP，简单而粗暴，今天的Connection Reset更多的是出现在使用Google的搜索，当你搜某些关键词时就出这个错了。</p>
<figure id="attachment_5122" aria-describedby="caption-attachment-5122" style="width: 593px" class="wp-caption aligncenter"><img decoding="async" loading="lazy" class="size-full wp-image-5122" title="该页无法显示 Connection Reset" src="https://coolshell.cn/wp-content/uploads/2011/08/connection-reset.png" alt="" width="593" height="365" srcset="https://coolshell.cn/wp-content/uploads/2011/08/connection-reset.png 593w, https://coolshell.cn/wp-content/uploads/2011/08/connection-reset-300x184.png 300w" sizes="(max-width: 593px) 100vw, 593px" /><figcaption id="caption-attachment-5122" class="wp-caption-text">该页无法显示 Connection Reset</figcaption></figure>
<p>（全文完）<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" ><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/7490.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/06/f1-150x150.jpg" alt="性能调优攻略" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7490.html" class="wp_rp_title">性能调优攻略</a></li><li ><a href="https://coolshell.cn/articles/4102.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/25.jpg" alt="如何学好C语言" width="150" height="150" /></a><a href="https://coolshell.cn/articles/4102.html" class="wp_rp_title">如何学好C语言</a></li><li ><a href="https://coolshell.cn/articles/4077.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/7.jpg" alt="纯文本配置还是注册表" width="150" height="150" /></a><a href="https://coolshell.cn/articles/4077.html" class="wp_rp_title">纯文本配置还是注册表</a></li><li ><a href="https://coolshell.cn/articles/3013.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2010/09/biolab-150x150.jpg" alt="一些非常有意思的杂项资源" width="150" height="150" /></a><a href="https://coolshell.cn/articles/3013.html" class="wp_rp_title">一些非常有意思的杂项资源</a></li><li ><a href="https://coolshell.cn/articles/1998.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2009/12/operatingsystems-fanboys-150x150.jpg" alt="粉丝眼中的操作系统" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1998.html" class="wp_rp_title">粉丝眼中的操作系统</a></li><li ><a href="https://coolshell.cn/articles/1579.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2009/10/operating-systems-150x150.jpg" alt="一张关于操作系统的图" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1579.html" class="wp_rp_title">一张关于操作系统的图</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/5107.html">10大经典错误</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/5107.html/feed</wfw:commentRss>
			<slash:comments>47</slash:comments>
		
		
			</item>
	</channel>
</rss>
