Перечисление строковых констант с йотой - PullRequest
0 голосов
/ 06 сентября 2018

В следующем примере определяется серия номеров портов, начиная с 3333 с использованием 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"?

Не работает следующее:

FirstPort = string(iota + 3333)

Ни один не делает

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

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Цитирование из Спецификация: Йота:

В объявлении константы предварительно объявленный идентификатор iota представляет последовательное нетипизированное целое число константы .

Итак, iota предоставляет вам целочисленные константы. Если нам нужны string константы, нам нужно найти способ преобразовать целое число в его представление base-10 string. Таким способом должно быть константное выражение , иначе мы не сможем использовать его в объявлении константы.

К сожалению для нас, простой тип преобразование из целого числа в string не приведет к представлению числового значения в формате base-10, но:

Преобразование целочисленного значения со знаком или без знака в строковый тип приводит к строке, содержащей целочисленное представление UTF-8.

Таким образом, результатом будет string, содержащий одну руну, значение которой (код Unicode) является номером источника.

Вызывать также вызов функций «преобразователя», таких как strconv.Itoa() или fmt.Sprint(), поскольку вызов этих функций не может быть частью константного выражения, поэтому результат может использоваться только в объявлении переменной (не говоря уже о том, что мы не можем использовать iota, он разрешен только в объявлениях констант).

Но есть еще решение.

Я не думаю, что это стоит хлопот и потери читабельности, , но на самом деле вы можете определить string констант , хранящих растущие десятичные числа, используя iota.

Решение строит «полные» числа из цифр. Мы можем получить представление base-10 string, объединив цифры (как string значения) числа.

Последний вопрос, который необходимо решить для этого, - как «перечислить» цифры числа. Это простая арифметика:

  • Последняя цифра (в базе 10) номера: i % 10.
  • Предыдущая цифра i / 10 % 10.
  • Предыдущий i / 100 % 10.
  • И так далее ...

И чтобы получить rune для цифры (которая находится в диапазоне 0..9), мы можем просто добавить к ней '0' и преобразовать ее в string. И это все.

Вот как мы можем закодировать это для однозначного строкового номера:

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

Для двузначного числа:

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

Для трехзначного номера:

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?

Также не проблема, может быть достигнуто легко. Мы можем сдвинуть йоту, просто добавив к ней "начальный" номер. И это все, что нужно.

Давайте рассмотрим пример, где первое число будет 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
0 голосов
/ 06 сентября 2018

Вы создаете нетипизированные числовые константы. Если сомневаетесь, проверьте спецификацию . Чтобы создать строку с номером хоста и порта, вы можете просто использовать fmt.Sprintf примерно так:

package main

const (
    FirstPort = iota+3333
    SecondPort
    ThirdPort
)

func main() {
    hostPort := fmt.Sprintf("localhost:%d", FirstPort)
    fmt.Println(hostPort)
}

Вот и все, что нужно: Демо

...