为了账号安全,请及时绑定邮箱和手机立即绑定

用 iota 枚举字符串常量

用 iota 枚举字符串常量

Go
aluckdog 2023-03-29 17:17:21
以下示例使用 iota 定义了一系列从 3333 开始的端口号。package mainimport (    "fmt")const (FirstPort = iota+3333SecondPortThirdPort)func main() {    hostAndPort := "localhost:"+fmt.Sprint(SecondPort)    fmt.Printf("%s", hostAndPort )     // Output:    // localhost:3334}组合主机名和端口时,我想避免必须将端口常量包装在其中fmt.Sprint并简单地编写,例如,"localhost:"+SecondPort。有没有办法使用 iota 将端口号定义为字符串常量,例如"3334"?以下不起作用:FirstPort = string(iota + 3333)也没有FirstPort = fmt.Sprintf("%d", iota + 3333)
查看完整描述

2 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

引用自规范:Iota:

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

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

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

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

所以结果将是一个string持有单个符文,其值(Unicode 代码点)是源编号。

也不能调用诸如strconv.Itoa()orfmt.Sprint()之类的“转换器”函数,因为调用这些函数不能成为常量表达式的一部分,因此结果只能用于变量声明(更不用说我们不能使用 ,它iota只是常量声明中允许)。

但是还是有办法解决的。

我认为这不值得麻烦和可读性的损失,但实际上你string可以使用iota.

该解决方案从数字构建“完整”数字。string我们可以通过连接数字的数字(作为值)来获得以 10 为底的表示形式string

最后要解决的问题是如何“列出”数字的数字。这是简单的算术:

  • 数字的最后一位(以 10 为基数)是i % 10.

  • 前面的数字是i / 10 % 10

  • 之前的那个是i / 100 % 10

  • 等等...

要获得rune一个数字(在 的范围内0..9),我们可以简单地'0'对其进行加法,并将其转换为string. 就这样。

这就是我们如何将其编码为 1 位字符串数字:

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

对于 2 位数字:

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)

输出(在Go Playground上尝试):


00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

到目前为止一切顺利,但我们如何让它从 开始3333?


也不是问题,可以轻松实现。我们可以简单地通过向它添加一个“初始”数字来移动iota。这就是它所需要的。


让我们看一个例子,其中第一个数字是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)

}

上面的输出是预期的(在Go Playground上试试):


3339

3340

3341


查看完整回答
反对 回复 2023-03-29
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您正在创建无类型的数字常量。要创建带有主机和端口号的字符串,您可以fmt.Sprintf像这样简单地使用:


package main


const (

    FirstPort = iota+3333

    SecondPort

    ThirdPort

)


func main() {

    hostPort := fmt.Sprintf("localhost:%d", FirstPort)

    fmt.Println(hostPort)

}


查看完整回答
反对 回复 2023-03-29
  • 2 回答
  • 0 关注
  • 108 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信