视频教程-大会208年4月29日_第1页
视频教程-大会208年4月29日_第2页
视频教程-大会208年4月29日_第3页
视频教程-大会208年4月29日_第4页
视频教程-大会208年4月29日_第5页
免费预览已结束,剩余38页可下载查看

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论