#5 golang Типы данных - Go для начинающих

Ранее мы говорили об объявлении переменных, теперь разберем простые типы данных.

Тип int - целые числа

Тип int — платформозависимый тип в Go. На хранение значения выделяется либо 32 бита, либо 64 бита в зависимости от разряднсти вашей операционной системы.

При объявлении переменной с указанием int:

// int — платформозависимый тип, 32/64
var i int = 10

- разрядноостint выбирается автоматически. Если вас не устраивает разрядность или вы хотите большего контроля, то в Go поддержка от int8 до int64, которая позволяет хранить большие значения:

// int - платформозависимый тип, 32/64
var i int = 10
// автоматически выбранный int
var autoInt = -10
// Как тип можно указать: int8, int16, int32, int64
var bigInt int64 = 1<<32 - 1


Есть беззнаковый int — uint, он тоже может быть платформозависимым диапазона хранимых данных, к нему же относятся и более "точные" типы от uint8 до uint64:
Примеры:

// Беззнаковый платформозависимый тип, 32/64
var unsignedInt uint = 100500
//  Беззнаковый тоже может быть: uint8, unit16, uint32, unit64
var unsignedBigInt uint64 = 1<<64 - 1

Тип float - вещественные числа

Числа с плавающей точкой представлены как одинарной точности float 32, так и двойной точности.

// float32, float64
var pi float32 = 3.141
var e = 2.718
goldenRatio := 1.618

Для них тоже есть автоподстановка типа, автоугадывание типа, значение по умолчанию для них тоже ноль.

Тип bool - логический, булев тип

В логических переменных значение по умолчанию ноль, и оно тоже может угадываться автоматически.

// bool логический тип
var b bool // false по-умолчанию
var isOk bool = true
var success = true
cond := true

Тип complex - комплексные числа

Зато в go есть комплексные переменные и полный набор функций для работы с ними, объявлять можно так:

// complex64, complex128
var c complex128 = -1.1 + 7.12i
c2 := -1.1 + 7.12i

хотя на практике этот тип данных используется не очень часто.

Тип string - строки

Значение по умолчанию для строки — это пустая строка.
Строка объявляется в двойных кавычках, и при этом внутри этих двойных кавычек могут быть спецсимволы, такие как перенос строки либо символ табуляции.
// пустая строка по-умолчанию

var str string
// со спец символами
var hello string = "Привет!\n\tПривет2!"

Если же вы хотите писать "как есть", то есть чтобы даже спецсимволы выводились как обычный текст, то вы можете использовать обратные кавычки.

// без спец символов
var world string = `Привет!\n\tПривет2!`

Для сравнения можно запустить программу:

package main

import (
	"fmt"
)

func main() {
	var hello string = "Привет!\n\tПривет2!"
	var helloAsIs string = `Привет!\n\tПривет2!`
	fmt.Println("1) " + hello)
	fmt.Println("2) " + helloAsIs)
}

В терминале получим что-то вроде:

1) Привет!
	Привет2!
2) Привет!\n\tПривет2!

UTF-8 для строк "из коробки"

В go строки сразу, "из коробки" поддерживают UTF-8, поэтому вы можете там писать на практически любых алфавитах, в данном случае
на русском:

// UTF-8 доступен сразу из коробки
var helloWorld = "Привет, Мир!"

Одинарные кавычки в go используются для символов, которые объявляются с типом byte, который является по сути псевдонимом для uint8.

// одинарные кавычки для типа byte (uint8)
var rawBinary byte = '\x27'

Либо же для типа rune, который представляет собой полноценный UTF-8 символ (под капотом это uint32):

// Тип rune (uint32) для UTF-8 символов
var someRune rune = '*'

В go конечно же можно можно конкатенировать строки - а именно с помощью плюса:

helloWorld := "Привет Мир"
// конкатенация строк
andGoodMorning := helloWorld + " и доброе утро!"

При этом вы не можете заменить какой-то один символ строки, например так:

// Ошибка cannot assign to helloWorld[0]
helloWorld[0] = 72

- в данном случае получим ошибку.

Длина строки, подстрки, получение "символа"

Если вы попробуете получить длину строки, используя встроенную функцию len, то вы получите длину в байтах:

// получение длины строки
byteLen := len(helloWorld) // 19 байт

Часто в прикладных задачах нам нужно вовсе не это, ведь это не символы.

Если втри строки данные в кодировке utf, то один символ может занимать больше одного байта. Поэтому, если вы хотите получить
именно количество символов, придется воспользоваться специальной функцией RunCountInString из пакета utf8:

symbols := utf8.RuneCountInString(helloWorld) // 10 рун
// получение подстроки, в байтах, не символах!
hello := helloWorld[:12] // Привет, 0-11 байты
H := helloWorld[0] // byte, 72, не "П"

Также можно получить часть строки, подстроку, используя оператор срез. Для этого надо указать, начи-
ная с какого байта (включительно) и по какой байт (не включительно) вы хотите получить подстроку.
// получение подстроки, в байтах, не символах!
hello := helloWorld[:12] // Привет, 0-11 байты
H := helloWorld[0]
// byte, 72, не "П"
Еще одной особенностью строк является то, что их можно конвертировать в слайс байт, и обратно слайс
байт вы можете конвертировать в строку. Подробнее про слайсы мы поговорим позднее.
// конвертация в слайс байт и обратно
byteString = []byte(helloWorld)
helloWorld = string(byteString)