duanqianwei2485 2018-09-06 16:18
浏览 123
已采纳

用iota枚举字符串常量

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
}

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"?

The following doesn't work:

FirstPort = string(iota + 3333)

Neither does

FirstPort = fmt.Sprintf("%d", iota + 3333)
  • 写回答

2条回答 默认 最新

  • dongqie4402 2018-09-06 16:37
    关注

    Quoting from Spec: Iota:

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

    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.

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

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

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

    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).

    But there is still a solution.

    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.

    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:

    • The last digit (in base 10) of a number is i % 10.
    • The preceding digit is i / 10 % 10.
    • The one before that is i / 100 % 10.
    • And so on...

    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.

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

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

    For a 2-digit number:

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

    For a 3-digit number:

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

    Let's see it in action:

    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
    )
    

    Printing the results:

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

    Output (try it on the Go Playground):

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

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

    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.

    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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图