Golang閉パッケージの典型的な応用
10385 ワード
概要:
参考ブログ:
データの分離
このようにして、呼び出し者のデータを隔離し、指定した結果を出力することができる.あるいは、関数呼び出しの回数を計算したい場合があります.関数カウンタ://
func counter(f func()) func() int {
n := 0
return func() int {
f()
n += 1
return n
}
}
//
func foo() {
fmt.Println("call foo")
}
func main() {
cnt := counter(foo)
cnt()
cnt()
cnt()
fmt.Println(cnt())
}
/*
:
call foo
call foo
call foo
call foo
4
*/
counter
任意の入力値と戻り値が空の関数を受け入れ、同時に1つの閉パケットを返すことができ、ここで閉パケットの結果は関数の呼び出し回数である.この例では、cnt
閉パケットへの参照が終了するまで、閉パケットが破棄されない.1つの閉パケットは、外部参照がない場合にのみ、ステータスとともに破棄されます.パラメータを必要とする関数を記録する場合は、counter
渡すパラメータタイプを個別に渡す必要があります.
フィボナッチ数列:func makeFibGen() func() int {
f1 := 0
f2 := 1
return func() int {
f2, f1 = f1+f2, f2
return f1
}
}
func main() {
gen := makeFibGen()
for i := 0; i < 10; i++ {
fmt.Println(gen())
}
}
/*
:
1
1
2
3
5
8
13
21
34
55
*/
コード理解:makeFibGen()
は、フィボナッチ数列が何番目に実行されたかを示す閉パケットであり、閉パケットが与えられた結果はi
項数列の結果である.
関数の装飾とミドルウェアの作成
関数はGo言語の一等公民であり,関数のパラメータとして伝達することができる.アクセサリーやミドルウェアとは,関数がパラメータとして伝達される場合を指す.func wrapping(f func() string) {
fmt.Println("do my work...")
fmt.Println("wrapping function: ", f())
fmt.Println("my work finished !")
}
func sayHello() string {
return "Hello !"
}
func sayByeBye() string {
return "Bye Bye !"
}
func main() {
wrapping(sayHello)
wrapping(sayByeBye)
}
/*
:
do my work...
wrapping function: Hello !
my work finished !
do my work...
wrapping function: Bye Bye !
my work finished !
*/
1つの関数は、伝達された異なる関数に基づいて異なる反応を生成することができ、伝達された関数は本質的に閉パケットである.
Defer Work
このプロセスは主にJavascriptのコールバック関数と比較されます.例えば、JSでは次のようになります.doWork1(a, b, function(result) {
doWork2(result, function(result) {
doWork3(result, function(result) {
// use the final result here
});
});
});
console.log("hi!");
doWork1
関数コールバックdoWork2
、そしてdoWork2
関数コールバックdoWork3
、実行順はdoWork1
->doWork2
->doWork3
がありますが、次の関数は前の関数の状態にして、前の関数の処理結果に応じた処理が必要です.
Go言語では、閉パッケージを直接使用して解決します.go func() {
result := doWork1(a, b)
result = doWork2(result)
result = doWork3(result)
// Use the final result
}()
fmt.Println("hi!")
閉パッケージは、プログラムの実行状態をよく保存し、プログラムの論理をより明確にすることができます.
//
func counter(f func()) func() int {
n := 0
return func() int {
f()
n += 1
return n
}
}
//
func foo() {
fmt.Println("call foo")
}
func main() {
cnt := counter(foo)
cnt()
cnt()
cnt()
fmt.Println(cnt())
}
/*
:
call foo
call foo
call foo
call foo
4
*/
func makeFibGen() func() int {
f1 := 0
f2 := 1
return func() int {
f2, f1 = f1+f2, f2
return f1
}
}
func main() {
gen := makeFibGen()
for i := 0; i < 10; i++ {
fmt.Println(gen())
}
}
/*
:
1
1
2
3
5
8
13
21
34
55
*/
関数はGo言語の一等公民であり,関数のパラメータとして伝達することができる.アクセサリーやミドルウェアとは,関数がパラメータとして伝達される場合を指す.
func wrapping(f func() string) {
fmt.Println("do my work...")
fmt.Println("wrapping function: ", f())
fmt.Println("my work finished !")
}
func sayHello() string {
return "Hello !"
}
func sayByeBye() string {
return "Bye Bye !"
}
func main() {
wrapping(sayHello)
wrapping(sayByeBye)
}
/*
:
do my work...
wrapping function: Hello !
my work finished !
do my work...
wrapping function: Bye Bye !
my work finished !
*/
1つの関数は、伝達された異なる関数に基づいて異なる反応を生成することができ、伝達された関数は本質的に閉パケットである.
Defer Work
このプロセスは主にJavascriptのコールバック関数と比較されます.例えば、JSでは次のようになります.doWork1(a, b, function(result) {
doWork2(result, function(result) {
doWork3(result, function(result) {
// use the final result here
});
});
});
console.log("hi!");
doWork1
関数コールバックdoWork2
、そしてdoWork2
関数コールバックdoWork3
、実行順はdoWork1
->doWork2
->doWork3
がありますが、次の関数は前の関数の状態にして、前の関数の処理結果に応じた処理が必要です.
Go言語では、閉パッケージを直接使用して解決します.go func() {
result := doWork1(a, b)
result = doWork2(result)
result = doWork3(result)
// Use the final result
}()
fmt.Println("hi!")
閉パッケージは、プログラムの実行状態をよく保存し、プログラムの論理をより明確にすることができます.
doWork1(a, b, function(result) {
doWork2(result, function(result) {
doWork3(result, function(result) {
// use the final result here
});
});
});
console.log("hi!");
go func() {
result := doWork1(a, b)
result = doWork2(result)
result = doWork3(result)
// Use the final result
}()
fmt.Println("hi!")