




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Rethinking
Errors
for
Go
2Marcel
van
Lohuizen,
Go
core
team@mpvl_/mpvlmpvl@在Go
2中
處理錯誤的方式About
me2002年加入搜索引擎Borg(Kubernetes的靈感來源)創(chuàng)始成員2011年加入Go團(tuán)隊(duì)At since2002Search
engineFounding
member
Borg (inspirationfor
Kubernetes)Go
team
since
2011關(guān)于我r,
err
:=
os.Open(“foo.txt”)if
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}defer
r.Close()Semantics
!Why?error
handling
can
be
tricky首先明確語義!為什么?合理處理錯誤很難,往往讓人放不慎防func
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
error
{var
errerrorw
:=
client.Bucket(bkt).Object(dst).NewWriter(c)defer
func()
{
w.CloseWithError(err)
}if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,err)}return
nil}err
:=errPanickingw
:=
client.Bucket(bkt).Object(dst).NewWriter(c)defer
func()
{
w.CloseWithError(err)
}if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}return
err}var
errPanicking
=
errors.New(“panicking”)func
wrihteTaoGSn(c
ndet.lCoentexp,bakt,ndsit
cstring失,r
io敗.Reader)error{func
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
(err
error)
{w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)err
=
errPanickingdefer
func()
{if
err
!=
nil
{_
=
w.CloseWithError(err)}
else
iferr
=
w.Close();
err
!=
nil
{err
=
fmt.Errorf(“oh
noes:
%v”,
err)}}if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}return
err}return
error
from
Close
失敗func
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
(err
error)
{w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)err
=
errPanickingdefer
func()
{if
err
!=
nil
{_=
w.CloseWithError(err)}
else
if
err
=
w.Close();
err
!=
nil
{err
=
fmt.Errorf(“oops:
%v”,
err)}}()if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{returnfmt.Errorf(“oops:
%v”,
err)}return
nil}var
errPanicking
=
errors.New(“panicking”)Awkward!尷尬!how
to
approach
simplifying
this?semantics
!如何簡化這些?首先明確語義!Closeerrorerrorpanicerror和panic的相似之處在Go中被忽視了there
is
overlapnot
recognized
in
Goan
error
is
recoverablepanic
is
not(sort
of)error是可恢復(fù)的panic卻不是(某種意義上)/mpvl/errc/mpvl/errdrecords
all
errors,including
panics,in
a
single
place將error和panic指向唯一一個變量自動化繁冗的控制流程automate
tediouscontrol
flowfunc
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
(err
error)
{w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)err
=
errPanickingdefer
func()
{if
err
!=
nil
{_
=
w.CloseWithError(err)}
else
if
err
=
w.Close();
err
!=
nil
{err
=
fmt.Errorf(“oops:
%v”,
err)}}()if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}return
nil}var
errPanicking
=
errors.New(“panicking”)func
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
(err
error)
{e
:=
errc.Catch(&err)defer
e.Handle()w
:=client.Bucket(bkt).Object(dst).NewWriter(c)e.Defer(w.CloseWithError,
msg(“oops”))_,
err
=
io.Copy(w,
r)e.Must(err,
msg(“oops”))return
nil}package
/mpvl/errcfunc
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
error
{return
errd.Run(func(e
*errd.E)
{w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)e.Defer(w.CloseWithError,
msg(“oops”))_,
err
=
io.Copy(w,r)e.Must(err,
msg(“oops”))}}package
/mpvl/errdw
:=
client.Bucket(bkt).Object(dst).NewWriter(c)err
=
errPanickingdefer
func()
{if
err
!=
nil
{_
=
w.CloseWithError(err)}
else
if
err
=
w.Close();
err
!=
nil
{err
=
fmt.Errorf(“oops:
%v”,
err)}}()if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}return
nile
:=
errc.Catch(&err)defer
e.Handle()w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)e.Defer(w.CloseWithError,
msg(“oops”))_,
err
=
io.Copy(w,
r)e.Must(err,
msg(“oops”))return
nil/mpvl/errdareErr
Dare如何在Go中做到這些?How
to
translate
this
tothe
Go
language?Other
issuesComplex
and
tedious
control
flowRepetition
of
wrappersRepetition其它問題繁冗的流程控制添加上下文的重復(fù)代碼重復(fù)代碼func
writeToGS(c
net.Context,
bkt,
dst
string,
r
io.Reader)
(err
error)
{w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)err
=
errPanickingdefer
func()
{if
err
!=
nil
{_=
w.CloseWithError(err)}
else
if
err
=
w.Close();
err
!=
nil
{err
=
fmt.Errorf(“oops:
%v”,
err)}}()if
_,
err
=
io.Copy(w,
r);
err
!=
nil
{return
fmt.Errorf(“oops:
%v”,
err)}return
nil}var
errPanicking
=
errors.New(“panicking”)Go
2
Draftfunc
writeToGS(c
context,
bkt,
dst
string,
r
io.Reader)
error
{handle
err
{
return
errors.Wrap(err)
}w
:=
client.Bucket(bkt).Object(dst).NewWriter(c)defer
err
{try
w.CloseWithError(err)
}try
io.Copy(w,r)return
nil}Go
2
初稿defer
err
{
…
}err被設(shè)定為PanicError(如果有panic發(fā)生)或者函數(shù)返回的錯誤或者只傳遞函數(shù)返回的錯誤,而另外添加一個內(nèi)置函數(shù)用以檢查panic狀態(tài)err
is
set
to
a
PanicError,
if
there
is
a
panic,
or
thereturned
error
value
otherwisealternatively,
pass
returned
error
only
and
have
abuiltin
to
peek
panic
statetry
<expr>Strips
last
evaluated
valueType
of
“try
os.Open(…)”
is
*FileOn
error,record
the
error
and
call
thehandler
chain.Within
defers
a
previous
error
isnot
overwrittenReturns from
the
function去掉最后一個返回值?"try
os.Open(...)"的類型是*File<expr>發(fā)生錯誤時保存錯誤并 錯誤處理函數(shù)在defer語句中,若已經(jīng)存在錯誤,則其不會被覆蓋返回函數(shù)handle
err
{
…
}handle定義一個在try發(fā)現(xiàn)錯誤時執(zhí)行的語句塊以內(nèi)聯(lián)方式執(zhí)行從而保留行號信息變量(err)只在語句塊中可見handle
defines
a
block
to
be
executed
when
a
try
detects
an
errorexecuted
in
place
to
preserve
line
numberinfovariable
name
(err)
only
visible
in
blockeach
block
may
have
itsown
handlerinside-out
execution
haltswhen
one
returnsimplicit
handler
that
returnserror
and
zero
valuesfunc
foo()
error
{msg
:=“foo”handle
err
{
return
wrap(err,msg)
}{handle
err{msg
=
“bar”
}…}}每個語句塊可以擁有它自己的錯誤處理函數(shù)自內(nèi)而外的執(zhí)行直到執(zhí)行return語句無return語句時,默認(rèn)的處理函數(shù)將返回錯誤和零值func
EigHerm(a
Const)
(*Mat,
[]float64,
error)
{if
err
:=
errNonPosDims(a);
err
!=
nil
{return
nil,
nil,
err}if
err
:=
errNonSquare(a);
err
!=
nil
{return
nil,
nil,
err}if
err
:=
errNonHerm(a);
err
!=
nil
{return
nil,
nil,
err}returneigHerm(cloneMat(a),
DefaultTri)}//
Computes
the
eigenvalue
factorization
of
a
Hermitian
matrix.func
EigHerm(a
Const)
(*Mat,
[]float64,
error)
{try
errNonPosDims(a)try
errNonSquare(a)try
errNonHerm(a)return
eigHerm(cloneMat(a),
DefaultTri)}}}()_,
err
=
io.Copy(w,
r)return
err}var
errPanicking
=
errors.New(“panicking”)obj
:=
client.Bucket(“b”).Object(“d”)return
errfunToGS(c
net.Context,
r
io.Reader)
error{
funToGS(cnet.Context,rio.Reader)error{obj:=
client.Bucket(“b”).Object(“d”)w
:=
obj.NewWriter(c)
w
:=
obj.NewWriter(c)err
:=
errPanicking
defer
err
{
try
w.CloseWithError(err)
}defer
func()
{if
err
!=
nil
{
_,
err
:=
io.Copy(w,r)_
=
w.CloseWithError(err)}
else
if
err1
=
w.Close();
err1
!=
nil
{
}err=
err1How
to
fix
CloseWithErr?collect
errors
in
one
placedeprecate
faulty
APIbuiltin
function
panicking()如何改正CloseWithErr?集中錯誤于一處放棄有問題的API內(nèi)置函數(shù)panicking()What
about
addingcontext
to
errors?如何為錯誤添加上下文?func
wrapper(err
error,
args
…interface{})
error
{if
err
==
nil
{return
nil}return
errors.E(err,
args…)}Functions
of
this
form
get
inlined這種形式的函數(shù)將變?yōu)橐恍袃?nèi)聯(lián)函數(shù)p,
err
:=
s.capture(ctx,
in.GetReservation())if
err
!=
nil
{return
nil,
errors.Wrap(err,
"capturingproposal")}r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=
blacklist(r)if
err
:=
validate.RequestFoo(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
"with
foo")}return
&request{},
nil}if
err
:=
validate.RequestBar(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
“with
bar")}return
&request{},
nilp,err
:=
s.capture(ctx,
in.GetReservation())try
errors.Wrap(err,
"capturing
proposal")r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=
blacklist(r)err
:=
validate.RequestFoo(r)try
errors.Wrap(err,
"with
foo”)return
&request{},
nil}err
:=
validate.RequestBar(r)try
errors.Wrap(err,
“with
bar")return
&request{},
nilp,
err
:=
s.capture(ctx,
in.GetReservation())if
err
!=
nil
{return
nil,
errors.Wrap(err,
"capturing
proposal")}r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=
blacklist(r)if
err
:=
validate.RequestFoo(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
"with
foo")}return
&request{},
nil}if
err
:=
validate.RequestBar(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
“with
bar")}return
&request{},
nilp,
err
:=
s.capture(ctx,
in.GetReservation())try
e(err,
"capturing
proposal")r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=
blacklist(r)try
e(validate.RequestFoo(r),
"with
foo")return
&request{},
nil}try
e(validate.RequestBar(r),
“with
bar")return
&request{},
nilp,
err
:=
s.capture(ctx,
in.GetReservation())if
err
!=
nil{return
nil,
errors.Wrap(err,
“capturing
…”)}r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=
blacklist(r)if
err
:=
validate.RequestFoo(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
"with
foo")}return
&request{},
nil}if
err
:=
validate.RequestBar(r);
err
!=
nil
{return
nil,
errors.Wrap(err,
“with
bar")}return
&request{},
nilhandle
err
{
errors.Wrap(err,
“create
request"}p
:=
try
s.capture(ctx,
in.GetReservation())r
:=
p.reservationif
util.HasFoo(r.GetFoo())
{r.State.Blacklist
=blacklist(r)try
validate.RequestFoo(r)return
&request{},
nil}try
validate.RequestBar
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 重慶電力高等??茖W(xué)?!督y(tǒng)一建模語言UML》2023-2024學(xué)年第二學(xué)期期末試卷
- 保安證考試答題技巧提升辦法及答案
- 四川省廣安、眉山、內(nèi)江、遂寧2025年高三5月畢業(yè)考試生物試題理試題含解析
- 2025年保安證考試模擬題及答案解析
- 山東省濰坊市教科所2025屆高三下學(xué)期第三次月考化學(xué)試題試卷含解析
- 商丘幼兒師范高等??茖W(xué)?!洞髷?shù)據(jù)與會計專業(yè)認(rèn)知教育》2023-2024學(xué)年第二學(xué)期期末試卷
- 南通理工學(xué)院《房屋構(gòu)建原理》2023-2024學(xué)年第二學(xué)期期末試卷
- 福建省福州市倉山區(qū)師范大學(xué)附中2025年高考復(fù)習(xí)全程精練模擬卷(全國I卷)生物試題含解析
- 蘭州大學(xué)《鋼筋混凝土結(jié)構(gòu)與砌體結(jié)構(gòu)》2023-2024學(xué)年第一學(xué)期期末試卷
- 浙江省“溫州十校聯(lián)合體”2024-2025學(xué)年高三七校聯(lián)考生物試題試卷含解析
- 二年級上冊美術(shù)教案及教學(xué)反思-3.7 美麗的葉子丨嶺南版
- 工程項(xiàng)目造價控制措施
- 電子印鑒卡講解
- 二方審核計劃
- 山西國際能源集團(tuán)有限公司所屬企業(yè)招聘(必考題)模擬卷及答案
- 盤筑成型專題知識培訓(xùn)
- (完整版)CST使用教程
- Q∕SY 02098-2018 施工作業(yè)用野營房
- DBT 29-217-2019 天津市巖棉外墻外保溫系統(tǒng)應(yīng)用技術(shù)規(guī)程
- 最新肺結(jié)核診斷和治療指南
- 管束式集裝箱 文檔
評論
0/150
提交評論