3.4延期キーワード
延期移動して、それがキーワードの言語と同じである行きます。リソースの解放のために延期、それは関数が戻る前に呼び出されます。一般的には次のモードを使用します。
f,err := os.Open(filename)
if err != nil {
panic(err)
}
defer f.Close()
複数の延期表現がある場合は、コールスタックは、バックと呼ばれる最初の式を延期、順番に似ています。
理解が延期に十分な深でない場合は、一緒に使用する場合でも、使用することは、特にバンドという名前のリターン・パラメータを使用して、ピットの一部を踏むことがあります。簡単な出会いを延期使用を初めて目を延期説明実装する前に。
ピットは、使用を延期すると
のは、いくつかの例を見てみましょう。例1:
func f() (result int) {
defer func() {
result++
}()
return 0
}
例2:
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
例3:
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
読者は、コードを実行する彼らの心になり、その後、確認するために、再びそれを実行しないでください。
実施例3は、正解でない場合、正しい答えは0例1ないが、実施例2は、...... 6正解10ありません
復帰前に実施を延期します。この中で 、公式文書には、明確に記載されています。声明ではありませんxxxのアトミック命令を返し、あなたはピット延期を使用する場合、最も重要なことは理解している踏まないでください!
この関数は、プロセスがこれです返します。割り当ての戻り値を与え、その式を延期呼び出し、そして最終的に呼び出し元の関数に戻ります。
関数が値を返した後、式は呼び出し元の関数に戻る前に、設定することができる延期し、戻り値を変更し、機能は、最終的な値は、あなたの想像力と矛盾しているが返されます。
実際には、単純な変換ルールがそれを書き換えると、それは混乱しないでしょう、延期使用して。書き換え規則は、return文を2つに分割され、書き込みXXXは以下のように書き換えられます返すことです。
返回值 = xxx
调用defer函数
空的return
例1を見て、それは次のように書き換えることができます。
func f() (result int) {
result = 0 //return语句不是一条原子调用,return xxx其实是赋值+ret指令
func() { //defer被插入到return之前执行,也就是赋返回值和ret指令之间
result++
}()
return
}
だから、戻り値は1です。
例2を見て、それは次のように書き換えることができます。
func f() (r int) {
t := 5
r = t //赋值指令
func() { //defer被插入到赋值与返回之间执行,这个例子中返回值r没被修改过
t = t + 5
}
return //空的return指令
}
だから、結果は5です。
それはに書き換えられた後、最後に、実施例3を参照してください。
func f() (r int) {
r = 1 //给返回值赋值
func(r int) { //这里改的r是传值传进去的r,不会改变要返回的那个r值
r = r + 5
}(r)
return //空的return
}
したがって、この例の結果は1です。
復帰コールの前に確かに延期。しかし、それは表現の形としてではないかもしれません。その理由は、リターンXXX文の性質が割り当てとRETの間に挿入された延期、アトミック命令ではないので、最終的に、戻り値を変更する機会があるかもしれません。
の実現を延期
キーワードで延期キーワードを達成するために行くことがruntime.deferprocはなくruntime.newprocで呼び出すことを除いて、非常によく似ています。
延期が表示された場合は、挿入された命令は、関数の戻り、挿入コールruntime.deferreturnの前に置き、runtime.deferprocを呼び出します。
関数は、アセンブリコードに類似し、正常に戻ったとき。
add xx SP
return
それが延期文が含まれている場合は、アセンブラコードは次のようになります。
call runtime.deferreturn,
add xx SP
return
コールruntime.deferreturnがテーブルからスタックをオンにし、実行を延期する時期ゴルーチン制御構造は、そこに、テーブルレコード延期されているテーブルに記録runtime.deferproc式を呼び出すときに必要になります延期、と。