只是Go里面的Error Check比較不直觀而已,其實(shí)可以封裝一層讓它更好看的。比如Rust的ResultT, E,它包含了一個(gè)Ok(..)和Err(..),Ok表示正確,然后帶有正確的返回值,而Err則表示錯(cuò)誤,然后帶著錯(cuò)誤信息。這樣處理起來(lái)就比較好看了,你可以選擇忽略它,讓程序直接在出錯(cuò)的地方掛掉,像這樣someFunctionMayFail().unwrap(); // 要是出錯(cuò)了,就直接掛掉
創(chuàng)新互聯(lián)建站是一家專業(yè)提供安康企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、H5技術(shù)、小程序制作等業(yè)務(wù)。10年已為安康眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。
或者在掛掉的時(shí)候,帶一個(gè)自己的出錯(cuò)信息someFunctionMayFail().ok().expect("Expecting a xxxxx");
或者自己處理let return_val = match someFunctionMayFail() {
Ok(v) = v,
Err(err) = {
// Deal with the error
// for example:
// fail!("Fail!!!! {}", err);
}
};
當(dāng)然,我不是說(shuō)它和Go的那個(gè)Error Check有什么本質(zhì)的區(qū)別,反正都是處理錯(cuò)誤,但是我個(gè)人覺(jué)得Rust這樣寫(xiě)更舒服。
error 是一種內(nèi)建的接口類型,不需要引用 任何包就可以直接使用。error 接口只聲明了一個(gè) Error 方法,任何實(shí)現(xiàn)了該方法的結(jié)構(gòu)體都可以作為 error 來(lái)使用。
標(biāo)準(zhǔn)庫(kù) errors 包中的 errorString 就是實(shí)現(xiàn)了 error 接口的一個(gè)例子:
針對(duì) error 而言,異常處理包括如何檢查錯(cuò)誤,如何傳遞錯(cuò)誤。
為了解決這一問(wèn)題,Go 1.13 中引入了對(duì)error的優(yōu)化,最核心的內(nèi)容就是引入了 wrapError 這一新的 error 類型。
目錄結(jié)構(gòu): 都在src的目錄下
主要是web.go 和http.go 的交互,fbn.go做了一個(gè)簡(jiǎn)單的斐波那契數(shù)列
先看web.go:
```
package main //入口
import (
"exdefer/filelistenserver/fileting"
"log"
"net/http"
"os"
)
type appHandler func(writer http.ResponseWriter, request *http.Request) error ? //定義一個(gè)實(shí)現(xiàn)錯(cuò)誤的方法
func errW(handler appHandler) func(writer http.ResponseWriter, request *http.Request) { //實(shí)現(xiàn)上面的方法
return func(writer http.ResponseWriter, request *http.Request) {
err := handler(writer, request) //http 的response 和request?? 設(shè)置一個(gè)錯(cuò)誤的返回值
if err != nil { // 判斷一下
log.Print("Print array ", err.Error(), "\n") //打印log
code := http.StatusOK //code 默認(rèn)設(shè)置成200
switch { //switch選擇
case os.IsNotExist(err): //如果輸入的這個(gè)文件不存在
code = http.StatusNotFound //404
case os.IsPermission(err): //如果權(quán)限不夠
code = http.StatusForbidden //403
default: //否則的話
code = http.StatusInternalServerError //500
}
http.Error(writer, http.StatusText(code), code) //輸出 第一個(gè)參數(shù) 是response,第二個(gè)是 錯(cuò)誤描述,返回的狀態(tài)碼 在swoole里面是$response-end("") /狀態(tài)碼是$response-status("");大同小異
}
}
}
func main() {
//第一個(gè)值是你要走的url目錄 swoole里面通過(guò)document_root 進(jìn)行設(shè)置
http.HandleFunc("/list/", errW(fileting.Handlist)) //調(diào)用的http.go的包
err := http.ListenAndServe(":8888", nil) //監(jiān)聽(tīng)的端口 第二個(gè)值一般給nil
if err != nil {
panic(err)
}
}
```
http.go
```
package fileting //聲明包
import (
"io/ioutil"
"net/http"
"os"
)
func Handlist(writer http.ResponseWriter, request *http.Request) error { //方法 返回一個(gè)error
path := request.URL.Path[len("/list/"):] //切片 path訪問(wèn)為localhost:8888/list/xxx.txt 中的xxx.txt
file, err := os.Open(path) //分開(kāi)寫(xiě)了,兩個(gè)返回值
if err != nil {
//http.Error(writer, err.Error(), http.StatusInternalServerError)
return err //直接return err
}
defer file.Close() //defer 一下? open完要記得
all, err := ioutil.ReadAll(file) //對(duì)文件的讀取
if err != nil {
//panic(err)
return err
}
writer.Write(all) //reponse 里面的write 類似swoole $response-end()
return nil //如果沒(méi)有錯(cuò)誤返回nil
}
```
演示一下:
今日的學(xué)習(xí),結(jié)束
當(dāng)一個(gè)函數(shù)調(diào)用返回一個(gè)錯(cuò)誤時(shí),調(diào)用者應(yīng)當(dāng)負(fù)責(zé)檢查錯(cuò)誤并采取合適的處理應(yīng)對(duì)。根據(jù)情形,將有許多可能的處理場(chǎng)景。接下來(lái)我們看 5 個(gè)策略:
Go 語(yǔ)言的錯(cuò)誤處理有特定的規(guī)律。進(jìn)行錯(cuò)誤檢查之后,檢測(cè)到失敗的情況往往都在成功之前。如果檢測(cè)到的失敗導(dǎo)致函數(shù)返回,成功的邏輯一般不會(huì)放在 else 塊中而是在外層的作用域中。函數(shù)會(huì)有一種通常的形式,就是在開(kāi)頭有一連串的檢查來(lái)返回錯(cuò)誤,之后跟著實(shí)際的函數(shù)體一直到最后。