Цитирование из Спецификация: Йота:
В объявлении константы предварительно объявленный идентификатор 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