Константы
Неизменность - признак мастерства или ограниченности мышления, не знаю, чего именно...
Итак, мы отлично поработали над такой важной для любого языка программирования темой, как операторы. Были приведены разнообразные примеры, которые с одной стороны, оживили повествование, с другой же стороны, дали нам почувствовать, что нам уже становится тесно в рамках пройденного материала и хочется вкусностей - новых и разных. Что же, приступим незамедлительно!
Рассматривая ECR протокол HYPERCOM, мы узнали, что, по сути, этот протокол, как и многие подобные, базируется на ASCII. Таблица ASCII же, в свою очередь, содержит не только символы, представляющие цифры, знаки и буквы латиницы, но и так называемые управляющие символы, то есть такие символы в кодировке, которым не приписано графическое представление, но которые используются для управления устройствами, организации передачи данных и других целей. Любой из символов ASCII имеет свой байтовый эквивалент. Здесь наблюдается своеобразный дуализм в том, что всякий ASCII-based протокол может быть представлен как байтовый, что, в том числе, служит причиной появления "гибридных" протоколов, где часть байтов трактуется как управляющие или символьные ASCII, другая же - как наборы байтов, представляющих текст в иных кодировках, например cp-1251, или числа, приведенные к двух- или четырёхбайтовому виду. Таков, к примеру, аналогичный рассмотренному протоколу HYPERCOM, ECR протокол компании Банкомсвязь. Работая с управляющими символами ASCII, нам в первую очередь представилось удобным использовать константы.
Как объявляются константы?
Работа с константами в целом похожа на работу с переменными. В крупном проекте есть смысл вынести объявление констант в отдельный файл. Так же как переменные, константы могут быть объявлены как по одиночке, так и группами с применением круглых скобок.
package main
const DC2 = 0x12 //DEVICE CONTROL TWO
const (
STX = 0x02 // START OF TEXT
ETX = 0x03 // END OF TEXT
EOT = 0x04 // END OF TRANSMISSION
)
//Некоторые управляющие символы ASCII
Существует также возможность группового объявления в строку
package main
const ACK, NAK = 0x06, 0x15
// ACKNOWLEDGE and NEGATIVE ACKNOWLEDGE
Это только один из множества возможных примеров, который мы избрали как логичное продолжение рассмотренного ранее материала. В целом же константы окружают нас повсюду, олицетворяя саму по себе возможность существования нашего мира. Это может быть число Pi и постоянная Планка, гравитационная постоянная и скорость света в вакууме. В каждом подобном случае, будь то число Авогадро или простое количество сантиметров в дюйме - смело используем константы.
Генератор констант iota
Константы могут объявляться следующим способом:
package main
import "fmt"
const (
a = 1
b
c = "one"
d
)
func main(){
fmt.Println(a, b, c, d) // 1 1 one one
}
Однако, что толку от одинаковых констант? Настоящий полезный инструмент - генератор констант iota.
package main
import "fmt"
const (
Sunday = iota
Monday
Wednesday
Tuesday
Thursday
Friday
Saturday
)
func main(){
fmt.Println(Sunday, Monday, Wednesday, Tuesday, Thursday, Friday, Saturday)
}
//Результат:
//0, 1, 2, 3, 4, 5, 6
iota - на самом деле весьма мощный инструмент, в применении которого можно долго оттачивать своё искусство и проявлять изобретательность.
package main
import "fmt"
const (
Zero = 1 << iota
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten
)
func main(){
fmt.Println(Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten)
}
//Результат - таблица степеней двойки
//1 2 4 8 16 32 64 128 256 512 1024
Особенности констант в языке Go
Константы в языке Go являются выражениями, значение которых не может быть изменено в процессе выполнения программы. Это значение заранее известно компилятору, и вычисление его относится ко времени компиляции а не ко времени выполнения. Значения констант ограничиваются базовыми типами, а также именованными типами, производными от базовых. Внимательный читатель мог заметить, что при инициализации констант мы до сих пор ни разу не указывали явно тип, выводя его из присваиваемого значения. На самом же деле тип можно указывать явно, однако необходимо отметить, что в языке Go это делают нечасто, и это связано с определённой своеобразностью констант этом языке. Константы, объявленные без явного указания типа становятся нетипизированными. Числовые нетипизированные константы компилятор не привязывает к определённому типу, и они обрабатываются с повышенной точностью, и, таким образом, могут содержать в себе значения, превышающие разрядность базовых типов. Присвоение константе значения обычной переменной компилятором не допускается. При выполнении операций с константами, при необходимости, следует выполнять привидение типов. Проиллюстрируем сказанное примерами. Как и ранее, примеры местами будут содержать некоторые новые сущности и понятия, во избежание излишнего упрощения. Разумеется, значение всех действий объясняется в комментариях.
Объявление константы с явным указанием типа
package main
import "fmt"
//тип константы можно указать явно
const Pi float32 = 3.14
func main() {
fmt.Println(Pi)
fmt.Printf("%T", Pi) //узнать тип константы
}
//Результат:
//3.14
//float32
Объявление константы именованного типа, производного от базового
package main
import "fmt"
//именованный тип T, производный от базового
type T int
const C T = 5
func main() {
fmt.Println(C)
fmt.Printf("%T", C) //узнать тип константы
}
//Результат (ошибки нет):
//5
//main.T
А такие приёмы недопустимы
package main
import "fmt"
//именованный тип T, НЕ производный от базового
type T struct {
a, b int
}
const C T = T{1, 1}
var i int = 5
const C1 = i
//Результат (ошибки):
//const initializer T literal is not a constant
//const initializer i is not a constant
Использование нетипизированных констант (полезнейшая вещь!)
package main
import "fmt"
//Константы: количество бит в пебибайте и эксбибайте
const pebi = 1125899906842624
const exbi = 1152921504606846976
func main() {
fmt.Println(exbi/pebi) //математическая операция с операндами,
//превышающими разрядность 64 bit!
fmt.Printf("%T", exbi) //узнать тип константы
}
//Результат:
//1024
//constant 1152921504606846976 overflows int
Ещё один пример
package main
import "fmt"
//Количество метров в световом году (превышает 64 bit!)
const metersInLightYear = 9454254955488000
//Количество секунд в году
const secInYear = 31536000
func main() {
//Вычислим скорость света в м/с
var c = metersInLightYear / secInYear
fmt.Println(c)
}
//Результат:
//299792458
Приведение типов
package main
import "fmt"
//Число Pi
const Pi = 3.14
//Радиус
var radius byte = 0x03
func main() {
//Вычислим длину окружности
fmt.Println(2 * Pi * radius) // Ошибка!
fmt.Println(2 * Pi * float64(radius)) //Нужно приведение типов!
fmt.Printf("%T", Pi) //узнать тип константы
}
//Результат(нужно приведение типов):
//constant 6.28 truncated to integer
//18.84
//float64
Пожалуй, теперь мы неплохо подготовлены и осведомлены в важной теме - использование констант в языке Go. "С чувством глубокого удовлетворения" двигаемся далее!
Last updated
Was this helpful?