用iota枚举字符串常量 [英] Enumerating string constants with iota

查看:50
本文介绍了用iota枚举字符串常量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下示例使用iota定义了一系列从3333开始的端口号.

The following example defines a series of port numbers starting at 3333 using iota.

package main

import (
    "fmt"
)
const (
FirstPort = iota+3333
SecondPort
ThirdPort
)
func main() {
    hostAndPort := "localhost:"+fmt.Sprint(SecondPort)
    fmt.Printf("%s", hostAndPort ) 
    // Output:
    // localhost:3334
}

在组合主机名和端口时,我希望避免将端口常量包装在 fmt.Sprint 中,而只需编写例如"localhost:" + SecondPort .有没有一种方法可以使用iota将端口号定义为字符串常量,例如"3334" ?

When combining hostname and ports, I'd like to avoid having to wrap the port constant in fmt.Sprint and simply write, for example, "localhost:"+SecondPort. Is there a way to use iota to define the port numbers as string constants, e.g "3334"?

以下内容无效:

FirstPort = string(iota + 3333)

也不是

FirstPort = fmt.Sprintf("%d", iota + 3333)

推荐答案

引用自规格:Iota:

常量声明中,预声明的标识符 iota 表示连续的无类型整数常量.

Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants.

所以 iota 为您提供了整数常量.如果需要 string 常量,我们需要找到一种将整数转换为以10为底的 string 表示形式的方法.这种方式必须是常量表达式,否则我们不能在常量声明中使用它.

So iota provides you integer constants. If we want string constants, we need to find a way to convert an integer to its base-10 string representation. This way must be a constant expression, else we can't use it in a constant declaration.

对于我们来说,很不幸,一个简单的类型转换从整数到 string 不会产生以10为底的数值表示形式,但是:

Unfortunately for us, a simple type conversion from integer to string will not yield the base-10 representation of the numerical value, but:

将有符号或无符号整数值转换为字符串类型会产生一个包含整数的UTF-8表示形式的字符串.

Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer.

因此结果将是一个包含单个符文的 string ,该符文的值(Unicode代码点)是源编号.

So the result will be a string holding a single rune, whose value (the Unicode codepoint) is the source number.

还调用转换器"功能,例如 strconv.Itoa() fmt.Sprint() 退出这个问题,因为调用这些函数不能是常量表达式的一部分,所以结果只能在变量声明中使用(更不用说我们不能使用 iota ,它只能在常量中使用声明).

Also calling "converter" functions such as strconv.Itoa() or fmt.Sprint() is out of the question, as calling those functions cannot be part of a constant expression, so the result could only be used in a variable declaration (not to mention we couldn't use iota, it's only allowed in constant declarations).

但是仍然有解决方案.

我认为这不值得花心思,也不值得失去可读性,但是实际上,您可以使用 iota <定义不断增加的十进制数字的 string 常量/code>.

I don't think it is worth the hassle and the loss of readability, but actually you can define string constants holding increasing decimal numbers using iota.

该解决方案从数字中构建完整"数字.我们可以通过将数字的数字(作为 string 值)串联来获得以10为底的 string 表示形式.

The solution builds the "complete" numbers from digits. We can obtain the base-10 string representation by concatenating the digits (as string values) of the number.

要解决的最后一个问题是如何列出"数字.这是简单的算法:

Last question to solve for this is how to "list" the digits of a number. This is simple arithmetic:

  • 数字的最后一位数字(以10为底)是 i%10 .
  • 前面的数字是 i/10%10 .
  • 之前的那个是 i/100%10 .
  • 依此类推...

并且要获得数字的 rune (在 0..9 的范围内),我们可以简单地添加'0'并将其转换为 string .就是这样.

And to obtain the rune for a digit (which is in the range of 0..9), we can simply add '0' to it, and convert it to string. And that's all.

这是我们如何为1位数字的字符串号进行编码的方式:

This is how we can code this for a 1-digit string number:

n0 = string('0'+iota%10)

对于两位数的数字:

n00 = string('0'+iota/10%10) + string('0'+iota/1%10)

对于3位数字:

n000 = string('0'+iota/100%10) + string('0'+iota/10%10) + string('0'+iota/1%10)

让我们看看它的作用:

const (
    P00 = string('0'+iota/10%10) + string('0'+iota/1%10)
    P01
    P02
    P03
    P04
    P05
    P06
    P07
    P08
    P09
    P10
    P11
    P12
    P13
    P14
    P15
    P16
    P17
    P18
    P19
    P20
)

打印结果:

fmt.Printf("%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n%v\n",
    P00, P01, P02, P03, P04, P05, P06, P07, P08, P09,
    P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)

输出(在游乐场上尝试):

00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20

到目前为止还不错,但是我们如何使它从 3333 开始?

So far so good, but how do we make it start at 3333?

这也不是问题,可以轻松实现.我们可以通过简单地在iota上添加一个初始"数字来移位.这就是全部.

Also not a problem, can be achieved easily. We can shift the iota, simply by adding an "initial" number to it. And that's all it takes.

让我们看一个示例,其中第一个数字为 3339 :

Let's see an example where the first number will be 3339:

const (
    P3339 = string('0'+(iota+3339)/1000%10) +
        string('0'+(iota+3339)/100%10) +
        string('0'+(iota+3339)/10%10) +
        string('0'+(iota+3339)/1%10)
    P3340
    P3341
)

func main() {
    fmt.Println(P3339)
    fmt.Println(P3340)
    fmt.Println(P3341)
}

上述内容的输出是预期的(请在游乐场上尝试):

Output of the above is the expected (try it on the Go Playground):

3339
3340
3341

这篇关于用iota枚举字符串常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆