What's the Go equivalent of a C++ static const function variable?

huangapple go评论103阅读模式
英文:

What's the Go equivalent of a C++ static const function variable?

问题

在C++中,你可以这样写:

std::string foo()
{
    const static std::vector<std::string> unchanging_data_foo_uses = {"one", "two", "three"};
    ...
}

我一直认为这样做的一个重要优点是,这个成员只需要设置一次,然后在后续的调用中不需要做任何操作,它只是存在那里,以便函数可以完成它的工作。在Go语言中有没有一种好的方法来做到这一点呢?也许编译器足够聪明,能够看到变量的值不依赖于参数,那么它可以像上面的代码一样处理,不进行任何重新评估?

在我具体的情况下,我正在编写一个将数字转换为单词的Go函数(例如,42 -> "forty-two")。下面的代码可以工作,但是我对在每次调用时都需要设置字符串数组感到不舒服,特别是因为它是递归的:

func numAsWords(n int) string {

    units := [20]string{
        "zero",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine",
        "ten",
        "eleven",
        "twelve",
        "thirteen",
        "fourteen",
        "fifteen",
        "sixteen",
        "seventeen",
        "eighteen",
        "nineteen",
    }

    tens := [10]string{
        // Dummies here just to make the indexes match better
        "",
        "",

        // Actual values
        "twenty",
        "thirty",
        "forty",
        "fifty",
        "sixty",
        "seventy",
        "eighty",
        "ninety",
    }

    if n < 20 {
        return units[n]
    }

    if n < 100 {
        if n % 10 == 0 {
            return tens[n / 10]
        }

        return tens[n / 10] + "-" + units[n % 10]
    }

    if n < 1000 {
        if n % 100 == 0 {
            return units[n / 100] + " hundred"
        }

        return units[n / 100] + " hundred and " + numAsWords(n % 100)
    }

    return "one thousand"
}

以上是你要翻译的内容。

英文:

In C++ you can write things like this:

std::string foo()
{
const static std::vector&lt;std::string&gt; unchanging_data_foo_uses = {&quot;one&quot;, &quot;two&quot;, &quot;three&quot;};
...
}

I've always thought one important advantage of this is that this member only needs to be setup once and then on subsequent calls nothing needs to be done and it's just sitting there so that the function can do its work. Is there a nice way to do this in Go? Maybe the compiler is smart enough to see if a variable's value does not depend on the arguments then it can treat it like the above code and not do any re-evaluation?

In my specific case I am writing a Go function to convert a number into words (e.g. 42 -> "forty-two"). The following code works, but I feel dirty about work being done to setup the string arrays on every call, especially since it is recursive:

func numAsWords(n int) string {
units := [20]string{
&quot;zero&quot;,
&quot;one&quot;,
&quot;two&quot;,
&quot;three&quot;,
&quot;four&quot;,
&quot;five&quot;,
&quot;six&quot;,
&quot;seven&quot;,
&quot;eight&quot;,
&quot;nine&quot;,
&quot;ten&quot;,
&quot;eleven&quot;,
&quot;twelve&quot;,
&quot;thirteen&quot;,
&quot;fourteen&quot;,
&quot;fifteen&quot;,
&quot;sixteen&quot;,
&quot;seventeen&quot;,
&quot;eighteen&quot;,
&quot;nineteen&quot;,
}
tens := [10]string{
// Dummies here just to make the indexes match better
&quot;&quot;,
&quot;&quot;,
// Actual values
&quot;twenty&quot;,
&quot;thirty&quot;,
&quot;forty&quot;,
&quot;fifty&quot;,
&quot;sixty&quot;,
&quot;seventy&quot;,                                                                                                                                
&quot;eighty&quot;,
&quot;ninety&quot;,
}
if n &lt; 20 {
return units[n]
}
if n &lt; 100 {
if n % 10 == 0 {
return tens[n / 10]
}
return tens[n / 10] + &quot;-&quot; + units[n % 10]
}
if n &lt; 1000 {
if n % 100 == 0 {
return units[n / 100] + &quot; hundred&quot;
}
return units[n / 100] + &quot; hundred and &quot; + numAsWords(n % 100)
}
return &quot;one thousand&quot;
}

答案1

得分: 3

你可以使用全局变量,在Go语言中是完全可以接受的,尤其是对于特定情况。

虽然你不能在数组中使用const关键字,但你可以使用类似以下的方式:

// 注意,由于它们以小写字母开头,它们在包外部将不可用
var (
units = [...]string{...}
tens = [...]string{ ... }
)
func numAsWords(n int) string { ... }

playground

英文:

You can you global variables, it's completely acceptable in go, specially for that specific case.

And while you can't use the keyword const with arrays, you can use something like:

//notice that since they start with lower case letters, they won&#39;t be
// available outside this package
var ( 
units = [...]string{...}
tens = [...]string{ ... }
)
func numAsWords(n int) string { ... }

<kbd>playground</kbd>

答案2

得分: 2

在Go语言中,不存在静态变量的概念。然而,你仍然可以通过将它们标记为常量来实现你想要的效果。

在Go语言中,常量就是常量。它们在编译时创建,即使在函数中定义为局部变量也是如此。

更多信息请参考:https://golang.org/doc/effective_go.html#constants

英文:

The concept of static variables do not exist in Go.
However, you can still achieve what you want by marking them as constant.

> Constants in Go are just that—constant. They are created at compile
> time, even when defined as locals in functions
https://golang.org/doc/effective_go.html#constants

答案3

得分: 0

你可以在函数创建时定义这些变量,并将其保存在闭包中。你可以定义并立即调用一个匿名函数来创建这些数组,然后创建并返回你的函数。匿名函数的返回值(即你的函数)然后被赋值给一个全局变量。

这个解决方案完全是一个技巧 - 因为它非常难以阅读(数组里面是什么?),而且你滥用了闭包来避免污染全局命名空间。一个更好的想法可能是将你的函数作为类方法。

但是我的解决方案实现了你的目标:数组只定义一次,不会污染任何命名空间。

英文:

You can define those variables in a closure retained by your function when it is created. (You define and immediately call an anonymous function that creates these arrays, then creates and returns your function. The anonymous function's return value (your function) is then assigned to a global variable.

This solution is totally a hack - both because it's horribly unreadable (What's in that array?), and because you're abusing closures to avoid cluttering your global namespace. A better idea would probably to make your function a class method.

But my solution achieves your goals: arrays are only defined once, and don't clutter ANY namespace.

huangapple
  • 本文由 发表于 2014年8月23日 12:50:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/25458551.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定