英文:
How to implement static local variable in go
问题
我正在学习使用Go语言。我想要实现一个静态局部变量,以避免声明一个全局变量。但是我在闭包方面遇到了困难。我希望只在第一次调用函数时打印一条消息,而不是每次都打印。
以下是我的代码:
func append(path string, vars Vars) {
// 只发出一次警告
func() (func()){
var f bool
return func(){
if len(vars["hostlurl"]) == 0 && !f {
f = true
fmt.Println("Warning: missing hosturl.")
}
}
}()
// 追加操作
...
}
在这段代码中,局部代码if len(...
从未被调用。
有没有办法避免添加全局变量?
谢谢你的帮助。
英文:
I'm in the learning curve with go. I like like
Well, I would like to implement such a static local variable to avoid to declare a global one. But I struggle with closure. I would like to print a message only the first time the function is called, and not the other times.
Here is my code
func append(path string, vars Vars) {
// raise a warning only once
func() (func()){
var f bool
return func(){
if len(vars["hostlurl"]) == 0 && !f {
f = true
fmt.Println("Warning: missing hosturl.")
}
}
}()
// append
...
}
In this code the local code if len(...
is never called
Is there a way to avoid to add a global variable?
Thank you for your help
答案1
得分: 4
在Go语言中,没有"静态局部变量"的概念。
如果一个函数需要状态,你有多种选择。可以在Go Playground上尝试以下所有选项。
可以使用包级别的变量:
var state bool
func f1() {
if !state {
state = true
fmt.Println("f1() first")
}
fmt.Println("f1() called")
}
测试:
f1()
f1()
// 输出
f1() first
f1() called
f1() called
或者将状态(指针)作为参数传递:
func f2(state *bool) {
if !*state {
*state = true
fmt.Println("f2() first")
}
fmt.Println("f2() called")
}
测试:
var state bool
f2(&state)
f2(&state)
// 输出
f2() first
f2() called
f2() called
或者可以使用方法,状态可以存储在接收器中:
type foo struct {
state bool
}
func (v *foo) f3() {
if !v.state {
v.state = true
fmt.Println("foo.f3() first")
}
fmt.Println("foo.f3() called")
}
测试:
v := foo{}
v.f3()
v.f3()
// 输出
foo.f3() first
foo.f3() called
foo.f3() called
或者使用sync.Once
,它也是并发安全的:
var f2Once sync.Once
func f4() {
f2Once.Do(func() {
fmt.Println("f4() first")
})
fmt.Println("f4() called")
}
测试:
f4()
f4()
// 输出
f4() first
f4() called
f4() called
或者返回一个引用局部变量的闭包:
func f5() func() {
var state bool
return func() {
if !state {
state = true
fmt.Println("f5() first")
}
fmt.Println("f5() called")
}
}
测试:
fret := f5()
fret()
fret()
// 输出
f5() first
f5() called
f5() called
也可以使用函数变量,将闭包赋值给它:
var f6 = func() func() {
var state bool
return func() {
if !state {
state = true
fmt.Println("f6() first")
}
fmt.Println("f6() called")
}
}()
测试:
f6()
f6()
// 输出
f6() first
f6() called
f6() called
还可以将方法值用作函数:
type bar struct {
state bool
}
func (v *bar) f7() {
if !v.state {
v.state = true
fmt.Println("foo.f7() first")
}
fmt.Println("foo.f7() called")
}
var f7 = (&bar{}).f7
测试:
f7()
f7()
// 输出
f7() first
f7() called
f7() called
英文:
There are no "static local variables" in Go.
If a function needs a state, you have numerous options. Try all on the Go Playground.
You may use a package level variable:
var state bool
func f1() {
if !state {
state = true
fmt.Println("f1() first")
}
fmt.Println("f1() called")
}
Testing:
f1()
f1()
// Output
f1() first
f1() called
f1() called
Or pass the (pointer to) state as an argument:
func f2(state *bool) {
if !*state {
*state = true
fmt.Println("f2() first")
}
fmt.Println("f2() called")
}
Testing:
var state bool
f2(&state)
f2(&state)
// Output
f2() first
f2() called
f2() called
Or you may use a method and the state may be stored in the receiver:
type foo struct {
state bool
}
func (v *foo) f3() {
if !v.state {
v.state = true
fmt.Println("foo.f3() first")
}
fmt.Println("foo.f3() called")
}
Testing:
v := foo{}
v.f3()
v.f3()
// Output
foo.f3() first
foo.f3() called
foo.f3() called
Or use sync.Once
which is also concurrency safe:
var f2Once sync.Once
func f4() {
f2Once.Do(func() {
fmt.Println("f4() first")
})
fmt.Println("f4() called")
}
Testing:
f4()
f4()
// Output
f4() first
f4() called
f4() called
Or return a closure that refers to a local variable:
func f5() func() {
var state bool
return func() {
if !state {
state = true
fmt.Println("f5() first")
}
fmt.Println("f5() called")
}
}
Testing:
fret := f5()
fret()
fret()
// Output
f5() first
f5() called
f5() called
You may also use a function variable, assigning a closure to it:
var f6 = func() func() {
var state bool
return func() {
if !state {
state = true
fmt.Println("f6() first")
}
fmt.Println("f6() called")
}
}()
Testing:
f6()
f6()
// Output
f6() first
f6() called
f6() called
You may also use a method value as a function:
type bar struct {
state bool
}
func (v *bar) f7() {
if !v.state {
v.state = true
fmt.Println("foo.f7() first")
}
fmt.Println("foo.f7() called")
}
var f7 = (&bar{}).f7
Testing:
f7()
f7()
// Output
f7() first
f7() called
f7() called
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论