視頻教程-大會208年4月29日_第1頁
視頻教程-大會208年4月29日_第2頁
視頻教程-大會208年4月29日_第3頁
視頻教程-大會208年4月29日_第4頁
視頻教程-大會208年4月29日_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論