|
33 | 33 |
|
34 | 34 | ```html
|
35 | 35 |
|
36 |
| - <html lang="en"> |
37 |
| - <head> |
38 |
| - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
39 |
| - <title>找不到页面</title> |
40 |
| - <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
41 |
| - |
42 |
| - </head> |
43 |
| - <body> |
44 |
| - <div class="container"> |
45 |
| - <div class="row"> |
46 |
| - <div class="span10"> |
47 |
| - <div class="hero-unit"> |
48 |
| - <h1>404!</h1> |
49 |
| - <p>{{.ErrorInfo}}</p> |
50 |
| - </div> |
51 |
| - </div><!--/span--> |
52 |
| - </div> |
53 |
| - </div> |
54 |
| - </body> |
55 |
| - </html> |
| 36 | + <html lang="en"> |
| 37 | + <head> |
| 38 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| 39 | + <title>找不到页面</title> |
| 40 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 41 | + |
| 42 | + </head> |
| 43 | + <body> |
| 44 | + <div class="container"> |
| 45 | + <div class="row"> |
| 46 | + <div class="span10"> |
| 47 | + <div class="hero-unit"> |
| 48 | + <h1>404!</h1> |
| 49 | + <p>{{.ErrorInfo}}</p> |
| 50 | + </div> |
| 51 | + </div><!--/span--> |
| 52 | + </div> |
| 53 | + </div> |
| 54 | + </body> |
| 55 | + </html> |
56 | 56 | ```
|
57 | 57 | 另一个源码:
|
58 | 58 |
|
59 | 59 | ```html
|
60 | 60 |
|
61 |
| - <html lang="en"> |
62 |
| - <head> |
63 |
| - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
64 |
| - <title>系统错误页面</title> |
65 |
| - <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
66 |
| - |
67 |
| - </head> |
68 |
| - <body> |
69 |
| - <div class="container"> |
70 |
| - <div class="row"> |
71 |
| - <div class="span10"> |
72 |
| - <div class="hero-unit"> |
73 |
| - <h1>系统暂时不可用!</h1> |
74 |
| - <p>{{.ErrorInfo}}</p> |
75 |
| - </div> |
76 |
| - </div><!--/span--> |
77 |
| - </div> |
78 |
| - </div> |
79 |
| - </body> |
80 |
| - </html> |
| 61 | + <html lang="en"> |
| 62 | + <head> |
| 63 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| 64 | + <title>系统错误页面</title> |
| 65 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 66 | + |
| 67 | + </head> |
| 68 | + <body> |
| 69 | + <div class="container"> |
| 70 | + <div class="row"> |
| 71 | + <div class="span10"> |
| 72 | + <div class="hero-unit"> |
| 73 | + <h1>系统暂时不可用!</h1> |
| 74 | + <p>{{.ErrorInfo}}</p> |
| 75 | + </div> |
| 76 | + </div><!--/span--> |
| 77 | + </div> |
| 78 | + </div> |
| 79 | + </body> |
| 80 | + </html> |
81 | 81 |
|
82 | 82 | ```
|
83 | 83 | 404的错误处理逻辑,如果是系统的错误也是类似的操作,同时我们看到在:
|
84 | 84 |
|
85 | 85 | ```Go
|
86 | 86 |
|
87 |
| - func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
88 |
| - if r.URL.Path == "/" { |
89 |
| - sayhelloName(w, r) |
90 |
| - return |
91 |
| - } |
92 |
| - NotFound404(w, r) |
93 |
| - return |
94 |
| - } |
| 87 | + func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 88 | + if r.URL.Path == "/" { |
| 89 | + sayhelloName(w, r) |
| 90 | + return |
| 91 | + } |
| 92 | + NotFound404(w, r) |
| 93 | + return |
| 94 | + } |
95 | 95 |
|
96 |
| - func NotFound404(w http.ResponseWriter, r *http.Request) { |
97 |
| - log.Error("页面找不到") //记录错误日志 |
98 |
| - t, _ = t.ParseFiles("tmpl/404.html", nil) //解析模板文件 |
99 |
| - ErrorInfo := "文件找不到" //获取当前用户信息 |
100 |
| - t.Execute(w, ErrorInfo) //执行模板的merger操作 |
101 |
| - } |
| 96 | + func NotFound404(w http.ResponseWriter, r *http.Request) { |
| 97 | + log.Error("页面找不到") //记录错误日志 |
| 98 | + t, _ = t.ParseFiles("tmpl/404.html", nil) //解析模板文件 |
| 99 | + ErrorInfo := "文件找不到" //获取当前用户信息 |
| 100 | + t.Execute(w, ErrorInfo) //执行模板的merger操作 |
| 101 | + } |
102 | 102 |
|
103 |
| - func SystemError(w http.ResponseWriter, r *http.Request) { |
104 |
| - log.Critical("系统错误") //系统错误触发了Critical,那么不仅会记录日志还会发送邮件 |
105 |
| - t, _ = t.ParseFiles("tmpl/error.html", nil) //解析模板文件 |
106 |
| - ErrorInfo := "系统暂时不可用" //获取当前用户信息 |
107 |
| - t.Execute(w, ErrorInfo) //执行模板的merger操作 |
108 |
| - } |
| 103 | + func SystemError(w http.ResponseWriter, r *http.Request) { |
| 104 | + log.Critical("系统错误") //系统错误触发了Critical,那么不仅会记录日志还会发送邮件 |
| 105 | + t, _ = t.ParseFiles("tmpl/error.html", nil) //解析模板文件 |
| 106 | + ErrorInfo := "系统暂时不可用" //获取当前用户信息 |
| 107 | + t.Execute(w, ErrorInfo) //执行模板的merger操作 |
| 108 | + } |
109 | 109 |
|
110 | 110 | ```
|
111 | 111 | ## 如何处理异常
|
|
114 | 114 | 但是还有一种情况,有一些操作几乎不可能失败,而且在一些特定的情况下也没有办法返回错误,也无法继续执行,这样情况就应该panic。举个例子:如果一个程序计算x[j],但是j越界了,这部分代码就会导致panic,像这样的一个不可预期严重错误就会引起panic,在默认情况下它会杀掉进程,它允许一个正在运行这部分代码的goroutine从发生错误的panic中恢复运行,发生panic之后,这部分代码后面的函数和代码都不会继续执行,这是Go特意这样设计的,因为要区别于错误和异常,panic其实就是异常处理。如下代码,我们期望通过uid来获取User中的username信息,但是如果uid越界了就会抛出异常,这个时候如果我们没有recover机制,进程就会被杀死,从而导致程序不可服务。因此为了程序的健壮性,在一些地方需要建立recover机制。
|
115 | 115 | ```Go
|
116 | 116 |
|
117 |
| - func GetUser(uid int) (username string) { |
118 |
| - defer func() { |
119 |
| - if x := recover(); x != nil { |
120 |
| - username = "" |
121 |
| - } |
122 |
| - }() |
| 117 | +func GetUser(uid int) (username string) { |
| 118 | + defer func() { |
| 119 | + if x := recover(); x != nil { |
| 120 | + username = "" |
| 121 | + } |
| 122 | + }() |
123 | 123 |
|
124 |
| - username = User[uid] |
125 |
| - return |
126 |
| - } |
| 124 | + username = User[uid] |
| 125 | + return |
| 126 | +} |
127 | 127 | ```
|
128 | 128 | 上面介绍了错误和异常的区别,那么我们在开发程序的时候如何来设计呢?规则很简单:如果你定义的函数有可能失败,它就应该返回一个错误。当我调用其他package的函数时,如果这个函数实现的很好,我不需要担心它会panic,除非有真正的异常情况发生,即使那样也不应该是我去处理它。而panic和recover是针对自己开发package里面实现的逻辑,针对一些特殊情况来设计。
|
129 | 129 |
|
|
0 commit comments