(詳細な分析を、外出先から)延期中golangの適切な使用

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式を呼び出すときに必要になります延期、と。

おすすめ

転載: www.cnblogs.com/lgh344902118/p/11484781.html