Я давно размышлял, в каком "книжкином месте" поговорить о приведении типов. Почему бы не здесь? Раз так, приступим. Приведение типов - type conversion - в языке Go момент достаточно простой и в то же время важный. Синтаксически это выглядит так: выражение T(v) приводит значение v к типу T. Коротко и просто.
packagemainimport("fmt")funcmain(){//байт (uint8) значение 0x40 (HEX) соответствует символу "@"varbbyte=0x40varsstring=string(b)fmt.Println(s)})//Результат://@
В практике программирования часто значения одного типа присваиваются переменным другого типа. Детали же реализации данного процесса разнятся от языка к к языку. В отличие от языка C (а также многих других языков) в Go нет автоматического (неявного) преобразования или приведения типов. Поэтому присвоение или применение каких-либо операторов между сущностями различных типов всегда требует явного (explicit) приведения типов.
//Преобразованине типов не работает!variint=3.14//Ошибка: constant 3.14 truncated to integer
Как видите, привычку свободно обращаться с данными близких, но не идентичных типов, которую мы наверняка могли завести в процессе работы на некотором другом языке программирования, придётся изживать.
Но так ли всё просто с явным приведением типов? Углубимся в детали. Итак, без каких-либо проблем может быть произведено преобразование типов в том случае, когда эти типы относятся к одной и той же категории типов данных (целочисленные, вещественные) при условии, что вы проследите за отсутствием переполнения преобразуемого типа, либо результата математического выражения, в котором использовалось такое преобразование. Неизбежно забегая вперёд отметим, что вполне взаимопреобразуемы будут строки и срезы байтов и рун ([]byte, []rune). Успешным будет и приведение структур, совпадающих сигнатурно. Приведение вещественного типа к целочисленному приведёт к потере (не округлению!) дробной части. Небрежность в соблюдении размерности типов - к переполнению.
Наконец, ожидаемо существуют преобразования, которые не могут быть совершены.
package main
import (
"fmt"
)
func main() {
var a int = 10
var b byte = 0x01
//Ошибка: invalid operation: a + b (mismatched types int and byte)
fmt.Println(a + b)
//а так - сработает. Вы ВЫНУЖДЕНЫ сделать явное приведение!
fmt.Println(a + int(b))
}
package main
import (
"fmt"
)
func main() {
f := 3.14
fmt.Println(int(f))//потеряли дробную часть
i := 256
fmt.Println(byte(i))//переполнение типа
}
//Результат:
//3
//0
package main
import (
"fmt"
)
func main() {
fmt.Println(bool(0)) // 0 не означает false!
fmt.Println((*int)(0))
}
//Результат:
//cannot convert 0 (type untyped int) to type bool
//cannot convert 0 (type int) to type *int