为Go中的函数预计算简单值

为Go中的函数预计算简单值,go,ocaml,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

我刚开始使用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
绑定到一个函数,该函数接受两个参数并可能返回一个网页,但在内部,我首先创建一个到
templ
的本地绑定(此绑定仅在
render\u page
的定义中可见,并且计算仅发生一次)然后在匿名函数中使用该绑定,这是绑定到
render\u page
的实际值。因此,当调用
render\u page
时,
temp
不会每次重新编译:它只是从闭包环境中获取

在围棋中完成这样的事情有一个共同的模式吗?我想尽量避免使用全局变量。我知道“全局”变量可能被限制在包的名称空间中,这就是我目前正在做的,但我想将这些预计算表达式的可见性限制在只需要它们的函数中


谢谢!

不熟悉Ocaml,所以不能100%确定这个Go示例是否是您要查找的,但是您可以在Go中定义一个函数,该函数可以预先计算某些内容,然后返回一个匿名函数,该函数在内部使用预先计算的值

例如,如果您这样做:

func matcher(pattern string) func(string) bool {
    regExp := regexp.MustCompile(pattern)
    return func(s string) bool {
        return regExp.MatchString(s)
    }
}
然后通过执行以下操作创建其中一个函数:

myMatcher := matcher("123")
然后可以多次调用
myMatcher(“某物”)
,并且不会每次编译regexp表达式,因为它在调用
matcher
函数时已经编译过

这是一个工作的围棋场:

我认为一个结束(类似于@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

除了这里的其他答案外,请注意,定义闭包后,可以将其绑定到全局变量,并将其与其他函数一样处理。 以下是eugenioy的略作修改:

var scan = matcher("123")

func main() {
    fmt.Println(scan("456"))
    fmt.Println(scan("123"))
}
这里,
scan
是一个全局闭包,与您在OCaml中所做的非常接近


Go没有函数局部静态变量。如果要在函数执行之间共享可变值,它必须是全局变量。可以将函数局部常量用于不可变值,但常量仅限于内置类型。还可以将该变量设为结构的成员,并将函数转换为方法,这取决于您的用例。您仍然需要确保重复使用该结构的相同实例。就我个人而言,我只会使用一个全局变量。您还可以将生成的闭包绑定到一个全局变量,然后您可以像其他函数一样使用它(请参阅我的答案)。