こんにちは。KOUKIです。
Goプログラマであり、SREエンジニアであり、DevOpsエンジニアという色々な仕事(雑用?)を日々こなしている、しがないWebエンジニアです。
今日は、表題の通り、Go言語でClosureを実装したいと思います。
<目次>
早速、実装
Closureのサンプルを以下に記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package main import "fmt" // Closures func incrementCounter() func() int { var iniNumber = 0 return func() int { iniNumber++ return iniNumber } } func main() { n1 := incrementCounter() fmt.Printf("n1 increments countrer#1: %d\n", n1()) fmt.Printf("n1 increments countrer#2: %d\n", n1()) n2 := incrementCounter() fmt.Printf("n2 increments countrer#1: %d\n", n2()) fmt.Printf("n2 increments countrer#2: %d\n", n2()) fmt.Printf("n1 increments countrer#2: %d\n", n2()) } |
1 2 3 4 5 6 |
$ go run main.go n1 increments countrer#1: 1 n1 increments countrer#2: 2 n2 increments countrer#1: 1 n2 increments countrer#2: 2 n1 increments countrer#2: 3 |
Closureのいいところ
Closureは、それ自身の外部から変数(ここでは、iniNumber)を参照する関数です。
メリットとして、iniNumberを外部から隔離(isolation)できることです。
先に記述したClosure(incrementCounter)は、変数n1/n2にそれぞれ代入しており、その内部に存在するiniNumberは各変数内で完全に独立しています。
つまり、一方の変数の変更がもう一方に影響を及ぼすことがないわけです。
この事は、堅牢なプログラミングを実装上で強みになります。
Closureがよく使われる場所
Go言語は、めちゃくちゃ早いAPIを実装できることがメリットです。
そして、APIサーバーを実装する際に、HTTP handlerをClosureで書くことが多いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package main import ( "fmt" "net/http" ) func adminCheck(h http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("user") != "admin" { http.Error(w, "Not Authorized", 401) return } fmt.Fprintf(w, "Admin Portal") h.ServeHTTP(w, r) }) } func newStatusCode(h http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTeapot) h.ServeHTTP(w, r) }) } func addHeader(h http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Foo", "Bar") h.ServeHTTP(w, r) }) } func writeResponse(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello PerfGo") } func main() { handler := http.HandlerFunc(writeResponse) http.Handle("/", addHeader(newStatusCode(handler))) http.Handle("/onlyHeader", addHeader(handler)) http.Handle("/onlyStatus", newStatusCode(handler)) http.Handle("/admin", adminCheck(handler)) fmt.Println("Server Start....") http.ListenAndServe(":1234", nil) } |
サーバーを起動して、Curlを打ってみましょう。
1 2 |
go run main.go Server Start... |
1 2 3 |
# curl例 curl -D - http://localhost:1234 |




挙動を変えたい時に便利ですよね。
おわりに
Go言語はめちゃくちゃ面白い言語です。それに文法が簡単で学びやすい。
日本でもこれから先、もっともっと流行っていくと思うので、私と一緒に勉強しましょう!
それでは、また!
コメントを残す
コメントを投稿するにはログインしてください。