付费下载
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Rethinking
Errors
for
Go
2Marcel
van
Lohuizen,
Go
core
team@mpvl_/mpvlmpvl@在Go
2中
处理错误的方式About
me2002年加入搜索引擎Borg(Kubernetes的灵感来源)创始成员2011年加入Go团队At since2002Search
engineFounding
member
Borg (inspirationfor
Kubernetes)Go
team
since
2011关于我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是可恢复的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其它问题繁冗的流程控制添加上下文的重复代码重复代码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被设定为PanicError(如果有panic发生)或者函数返回的错误或者只传递函数返回的错误,而另外添加一个内置函数用以检查panic状态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>发生错误时保存错误并 错误处理函数在defer语句中,若已经存在错误,则其不会被覆盖返回函数handle
err
{
…
}handle定义一个在try发现错误时执行的语句块以内联方式执行从而保留行号信息变量(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”
}…}}每个语句块可以拥有它自己的错误处理函数自内而外的执行直到执行return语句无return语句时,默认的处理函数将返回错误和零值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内置函数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这种形式的函数将变为一行内联函数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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年黑江盛达职业学院单招职业技能考试模拟试卷及参考答案详解(培优A卷)
- 2027年聊城现代农业职业学院单招综合素质考试模拟试卷含答案详解(预热题)
- 2027年青岛中鲁职业学院高职单招职业适应性测试考试模拟试卷【综合卷】附答案详解
- 2026年内蒙古自治区鄂尔多斯市高职单招职业技能考试模拟试卷及参考答案详解(达标题)
- 2024年大连职业技术学院高职单招职业适应性测试考试模拟试卷【研优卷】附答案详解
- 2027年西安临港产业职业学院高职单招职业适应性测试考试模拟试卷及参考答案详解(模拟题)
- 2025年湖南湘西技师学院高职单招职业适应性测试考试题库含完整答案详解(名师系列)
- 2026年四川艺术职业学院高职单招职业技能考试模拟试卷含答案详解【培优B卷】
- 2024年四川省甘孜藏族自治州单招职业技能考试题库及参考答案详解(培优B卷)
- 2026年唐山海运职业学院高职单招职业技能考试模拟试卷含完整答案详解【夺冠系列】
- 钨钼矿开采过程土壤污染防治措施-洞察及研究
- GB/T 46412-2025资产管理碳资产管理体系应用指南
- 有机合成实验室安全培训课件
- 2025年中国农业科学院烟草研究所第二批公开招聘(4人)考试参考题库及答案解析
- 高标准农田知识培训课件
- 2025年征兵文化考试题及答案
- 总工会干部培训课件
- 2024-2025学年八年级下学期数学期中试题汇编《垂直平分线与角平分线》含答案解析
- 关于加强医药卫生领域廉政建设的意见(2025年版)解读
- 生产主管的转正述职报告
- 海南省海上搜救应急预案
评论
0/150
提交评论