2017-06-02 14 views
2

単純なWebプログラミングプロジェクトではGoを使い始めましたが、単一の関数のローカルな事前計算を簡単に行う方法を理解できません。これは例えば、私はOCamlの中でかなり頻繁に行うものです:OCamlのに慣れていない人のためにGoの関数の単純な値を事前計算する

(* maybe render_page is a handler function for an HTTP server or something *) 
let render_page = 
    (* let's say that Template.prepare takes a template string and returns its compiled representation *) 
    let templ = Template.prepare "user: {{.}}, group: {{.}}" in 
    (* return an anonymous function *) 
    fun user group -> 
    templ [user; group] 

、私は2つのパラメータを取り、おそらくWebページを返す関数に名前render_pageを結合していているもの以上起こって、内部的にはまずtemplへのローカルバインディングを作成しています(このバインディングはrender_pageの定義内でのみ表示され、計算は1回しか実行されません)。次に、匿名関数内のそのバインディングを使用します(実際の値はrender_pageにバインドされています)。したがって、render_pageを呼び出すと、毎回templは再コンパイルされません。クロージャ環境からフェッチされたばかりです。

Goでこれを実現する共通のパターンはありますか?可能な限りグローバル変数を避けたい。私は現在グローバル変数がパッケージの名前空間に限定されている可能性があることを認識していますが、これらの事前計算式の可視性を必要な機能だけに制限したい。

ありがとうございます!

+1

Goには、関数ローカル静的変数はありません。関数の実行間で変更可能な値を共有する場合は、グローバル変数でなければなりません。不変の値には関数ローカル定数を使用できますが、定数は組み込み型に限定されています。 – Adrian

+1

また、変数を構造体のメンバにし、そのユースケースに応じて関数をその構造体のメソッドに変換することもできます。構造体の同じインスタンスが確実に再利用されるようにする必要があります。個人的には私はただグローバルなものを使っています。 – Adrian

答えて

2

Ocamlに慣れていないので、このGoの例があなたが探しているものであれば、Goでいくつかのものをあらかじめ計算しておき、内部的にはpreを使う匿名関数を返す関数を定義できます計算された値。例えば

、あなたがこれを行う場合:

func matcher(pattern string) func(string) bool { 
    regExp := regexp.MustCompile(pattern) 
    return func(s string) bool { 
     return regExp.MatchString(s) 
    } 
} 

そして実行することにより、これらの機能のいずれかを作成します。あなたは、その後myMatcher("something")を複数回呼び出すことができ、および正規表現の表現ではないでしょう

myMatcher := matcher("123") 

matcher関数を呼び出すときに既にコンパイルされているので、毎回コンパイルされます。ここで

はこれに取り組んで行くの遊び場です:

https://play.golang.org/p/m3vBrYn4Dg

+0

結果のクロージャをグローバル変数にバインドし、他の関数と同様に使用することができます(私の答えを参照)。 – coredump

0

私は(すでにと答え@eugenioyものと同様の)閉鎖はあなたが得ようとしている最も近いと思います。ここでは他の回答に加えて

func main() { 
    userGroupTemplate := renderPage() 
    fmt.Println(userGroupTemplate("sberry", "StackOverflow")) 
    fmt.Println(userGroupTemplate("user1030453", "StackOverflow")) 
} 

func renderPage() func(user, group string) string { 
    templ := "user: %s, group: %s" 
    fmt.Println("template is created") 
    return func(user, group string) string { 
     return fmt.Sprintf(templ, user, group) 
    } 
} 

OUTPUT

template is created 
user: sberry, group: StackOverflow 
user: user1030453, group: StackOverflow 
0

、あなたはクロージャを定義したら、あなたはグローバル変数にバインドし、他の関数のように扱うことに注意してください。ここで

var scan = matcher("123") 

func main() { 
    fmt.Println(scan("456")) 
    fmt.Println(scan("123")) 
} 

scanあなたはOCamlの中で何をしたかに非常に近いグローバル閉鎖、次のとおりです。 はここeugenioyのわずかに変更さanswerです。

https://play.golang.org/p/Lc0SC53b-0

関連する問題