引数

2017-12-28 28 views
3

として延期で使用する方法を渡す私たちは、簡単にパラメータとして関数を渡すとdeferでそれを使用することができます。引数

func main() { 
    test(rec) 
} 

func test(f func(int)) { 
    defer f(10) 
    panic("test") 
} 

func rec(v int) { 
    e := recover() 
    fmt.Println(e) 
    fmt.Println(v) 
} 

これは動作します。 Playground


しかし、我々は方法に合格し、その方法でrecoverを呼び出すために何が必要な場合は?

type MyStruct struct { 
    Data string 
} 

func main() { 
    a := &MyStruct{} 
    test(a.Recover) 
} 

func test(f func(int)) { 
    defer f(10) 
    panic("test") 
} 

func (m *MyStruct) Recover(arg int) { 
    e := recover() 
    fmt.Println(e) 
    fmt.Println(arg) 
} 

ここで私は完全に理解していないいくつかの奇妙な動作をします。 Playground

メソッドが呼び出されるようですが、recovernilを返します。その後、(別の?)パニックがあります。 golangのドキュメントとGoogleの結果のどれも、私がそのような行動の理由を理解するのを助けたことはありません。私は何が欠けていますか?

答えて

3

recover()機能returns nil when not called directly from the deferred function

a.Recoverの通話は直接コールではありません。

回復呼び出し、メソッドラッパー関数を使用します

func main() { 
    a := &MyStruct{} 
    test(func(arg int) { a.Recover(arg, recover()) }) 
} 

func test(f func(int)) { 
    defer f(10) 
    panic("test") 
} 

func (m *MyStruct) Recover(arg int, e interface{}) { 
    fmt.Println(e) 
    fmt.Println(arg) 
} 

は別のオプションは、method expressionを使用することですが、これはおそらくあなたが達成しようとしているものから逸れている:

func main() { 
    a := &MyStruct{} 
    test(a, (*MyStruct).Recover) 
} 

func test(a *MyStruct, f func(*MyStruct, int)) { 
    defer f(a, 10) 
    panic("test") 
} 

func (m *MyStruct) Recover(arg int) { 
    e := recover() 
    fmt.Println(e) 
    fmt.Println(arg) 
} 
+0

それをドキュメント値からの呼び出しが直接呼び出しではないことはドキュメントからは分かりませんでしたが、今では... ありがとうございました! 渡された引数でメソッド値とメソッド式を区別する方法がないことを正しく理解していますか? –

+0

メソッド値を通じた呼び出しが直接呼び出しとみなされない理由を知っていますか? –

+1

メソッド値の引数の数は、基本となるメソッドの引数の数よりも1つ少なくなります。メソッド値の呼び出しはメソッドの直接呼び出しではありません。実行時に関数が与えられると、関数が単純関数、関数リテラル、メソッド式またはメソッド値であるかどうかを判断することはできません。 –