在Go中预先计算函数的简单值

时间:2017-06-02 20:36:59

标签: go ocaml

我刚开始使用Go进行简单的Web编程项目,但我无法弄清楚如何在单个函数中完成本地的简单预计算。这是我在OCaml中经常做的事情,例如:

(* 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]

对于那些不熟悉OCaml的人,上面发生的事情是我将名称render_page绑定到一个带有两个参数并且可能返回一个网页的函数,但在内部我首先创建一个本地绑定到{ {1}}(此绑定仅在templ的定义中可见,并且计算仅发生一次)然后在匿名函数中使用该绑定,这是绑定到render_page的实际值。因此,当您调用render_page时,render_page不会每次都重新编译:它只是从闭包环境中获取。

在Go中有没有一种常见的模式来完成这样的事情?我想尽可能避免全局变量。我知道“全局”变量可能仅限于包的名称空间,这正是我目前所做的,但我想将这些预先计算的表达式的可见性限制为只需要它们所需的函数

谢谢!

3 个答案:

答案 0 :(得分:2)

不熟悉Ocaml,所以不是100%确定这个Go示例是否是你想要的,但你可以在Go中定义一个函数,它可以预先计算一些东西,然后返回一个内部使用pre-an的匿名函数计算值。

例如,如果你这样做:

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

然后通过执行以下操作创建其中一个函数:

myMatcher := matcher("123")

然后,您可以多次调用myMatcher("something"),并且每次调用matcher函数时都不会编译regexp表达式。

这是一个有效的Go游乐场:

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

答案 1 :(得分: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)
    }
}

<强>输出

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

答案 2 :(得分:0)

除了这里的其他答案之外,请注意,一旦定义了闭包,就可以将其绑定到全局变量并像其他函数一样对待它。 这是eugenioy的answer略有修改:

var scan = matcher("123")

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

在这里,scan是一个全局闭包,它与你在OCaml中所做的非常接近。

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