1 - Функции builtin
Описание функций builtin
func append
func append(slice []Type, elems ...Type) []Type
Встроенная функция append
добавляет элементы в конец слайса. Если он имеет достаточную емкость, целевой слайс переразбивается, чтобы вместить новые элементы. Если нет, выделяется новый базовый массив. Append возвращает обновленный слайс. Поэтому необходимо сохранить результат append, часто в переменной, содержащей сам слайс:
slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)
В качестве особого случая допустимо добавлять строку к байтовому слайсу, например:
slice = append([]byte(«hello »), «world»...)
func cap
Встроенная функция cap
возвращает емкость v
в зависимости от его типа:
- Массив: количество элементов в v (то же, что len(v)).
- Указатель на массив: количество элементов в *v (то же, что len(v)).
- Срез: максимальная длина, которую может достичь срез при повторном разрезании; если v равно nil, cap(v) равно нулю.
- Канал: емкость буфера канала в единицах элементов; если v равно nil, cap(v) равно нулю.
Для некоторых аргументов, таких как простое массивное выражение, результатом может быть константа. Подробности см. в разделе «Длина и емкость» спецификации языка Go.
func clear
func clear[T ~[]Type | ~map[Type]Type1](t T)
Встроенная функция clear
очищает карты и фрагменты.
- Для карт clear удаляет все записи, в результате чего карта становится пустой.
- Для слайсов clear устанавливает все элементы до длины слайса в нулевое значение соответствующего типа элемента.
Если тип аргумента является типовым параметром, набор типов типового параметра должен содержать только типы карт или слайсов, и clear выполняет операцию, подразумеваемую типовым аргументом. Если t равно nil, clear не выполняет никаких действий.
func close
func close(c chan<- Type)
Встроенная функция close
закрывает канал, который должен быть либо двунаправленным, либо только для отправки. Она должна выполняться только отправителем, никогда не получателем, и приводит к закрытию канала после получения последнего отправленного значения. После получения последнего значения из закрытого канала c любое получение из c будет выполняться без блокировки, возвращая нулевое значение для элемента канала. Форма
также установит ok в false для закрытого и пустого канала.
func complex
func complex(r, i FloatType) ComplexType
Встроенная функция complex
создает комплексное значение из двух значений с плавающей запятой. Действительная и мнимая части должны быть одинакового размера, либо float32, либо float64 (или приравниваемы к ним), и возвращаемое значение будет соответствующим комплексным типом (complex64 для float32, complex128 для float64).
func copy
func copy(dst, src []Type) int
Встроенная функция copy
копирует элементы из исходного слайса в целевой слайс. (В качестве особого случая она также копирует байты из строки в слайс байтов.) Исходный и целевой слайсы могут пересекаться. Copy возвращает количество скопированных элементов, которое будет минимальным из len(src) и len(dst).
func delete
func delete(m map[Type]Type1, key Type)
Встроенная функция delete
удаляет элемент с указанным ключом (m[key]) из карты. Если m равно nil или такого элемента нет, delete не выполняет никаких действий.
func imag
func imag(c ComplexType) FloatType
Встроенная функция imag
возвращает мнимую часть комплексного числа c. Возвращаемое значение будет иметь тип с плавающей запятой, соответствующий типу c.
func len
Встроенная функция len
возвращает длину v в соответствии с его типом:
- Массив: количество элементов в v.
- Указатель на массив: количество элементов в *v (даже если v равен nil).
- Срез или карта: количество элементов в v; если v равен nil, len(v) равен нулю.
- Строка: количество байтов в v.
- Канал: количество элементов в очереди (непрочитанных) в буфере канала; если v равно nil, len(v) равно нулю.
Для некоторых аргументов, таких как строковый литерал или простое массивное выражение, результатом может быть константа. Подробности см. в разделе «Длина и емкость» спецификации языка Go.
func make
func make(t Type, size ...IntegerType) Type
Встроенная функция make
выделяет и инициализирует объект типа slice
, map
или chan
(только). Как и в случае с new
, первый аргумент является типом, а не значением. В отличие от new, тип возвращаемого значения make совпадает с типом его аргумента, а не является указателем на него. Спецификация результата зависит от типа:
- Срез: размер определяет длину. Емкость среза равна его длине. Можно указать второй целочисленный аргумент, чтобы задать другую емкость; она не должна быть меньше длины. Например, make([]int, 0, 10) выделяет базовый массив размером 10 и возвращает срез длиной 0 и емкостью 10, который поддерживается этим базовым массивом.
- Карта: выделяется пустая карта с достаточным пространством для хранения указанного количества элементов. Размер может быть опущен, в этом случае выделяется небольшой начальный размер.
- Канал: буфер канала инициализируется с указанной емкостью буфера. Если размер равен нулю или опущен, канал не имеет буфера.
func max
func max[T cmp.Ordered](x T, y ...T) T
Встроенная функция max
возвращает наибольшее значение из фиксированного числа аргументов типов cmp.Ordered
. Должно быть как минимум один аргумент. Если T является типом с плавающей запятой и любой из аргументов является NaN, max вернет NaN.
func min
func min[T cmp.Ordered](x T, y ...T) T
Встроенная функция min
возвращает наименьшее значение из фиксированного числа аргументов типов cmp.Ordered. Должно быть как минимум один аргумент. Если T является типом с плавающей запятой и любой из аргументов является NaN, min вернет NaN.
func new
Встроенная функция new
выделяет память. Первый аргумент — это тип, а не значение, и возвращаемое значение — это указатель на вновь выделенное нулевое значение этого типа.
func panic
Встроенная функция panic
останавливает нормальное выполнение текущего goroutine.
Когда функция F вызывает panic, нормальное выполнение F немедленно останавливается. Все функции, выполнение которых было отложено F, выполняются обычным образом, а затем F возвращается к своему вызывающему. Для вызывающего G вызов F ведет себя как вызов panic, прекращая выполнение G и запуская все отложенные функции. Это продолжается до тех пор, пока все функции в выполняющемся goroutine не остановятся в обратном порядке. В этот момент программа завершается с ненулевым кодом выхода. Эта последовательность завершения называется паникой и может контролироваться встроенной функцией recover.
Начиная с Go 1.21, вызов panic с нулевым значением интерфейса или нетипизированным nil вызывает ошибку выполнения (другой вид паники). Настройка GODEBUG panicnil=1 отключает ошибку выполнения.
func print
Встроенная функция print
форматирует свои аргументы способом, специфичным для реализации, и записывает результат в стандартный поток ошибок. Print полезна для начальной загрузки и отладки; ее сохранение в языке не гарантируется.
func println
func println(args ...Type)
Встроенная функция println
форматирует свои аргументы способом, специфичным для реализации, и записывает результат в стандартный поток ошибок. Между аргументами всегда добавляются пробелы и добавляется новая строка. Println полезна для начальной настройки и отладки; ее сохранение в языке не гарантируется.
func real
func real(c ComplexType) FloatType
Встроенная функция real
возвращает действительную часть комплексного числа c. Возвращаемое значение будет иметь тип с плавающей запятой, соответствующий типу c.
func recover
Встроенная функция recover
позволяет программе управлять поведением goroutine, входящего в состояние паники.
Вызов recover внутри отложенной функции (но не в любой функции, вызываемой ею) останавливает последовательность паники, восстанавливая нормальное выполнение и извлекая значение ошибки, переданное вызову panic.
Если recover вызывается вне отложенной функции, он не останавливает последовательность паники. В этом случае, или когда goroutine не входит в состояние паники, recover возвращает nil.
До Go 1.21 recover также возвращала nil, если panic вызывалась с аргументом nil. Подробности см. в разделе [panic].
Пример
Функция recover()
используется для перехвата паники (panic) и восстановления нормального выполнения программы. Вот несколько практических примеров:
Пример 1: Базовое использование recover
package main
import "fmt"
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Start")
panic("something went wrong")
fmt.Println("This won't be executed")
}
Вывод:
Start
Recovered from panic: something went wrong
Пример 2: Восстановление после деления на ноль
package main
import "fmt"
func safeDivide(a, b int) (result int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
result = 0 // устанавливаем значение по умолчанию
}
}()
return a / b // может вызвать панику при b = 0
}
func main() {
fmt.Println(safeDivide(10, 2)) // 5
fmt.Println(safeDivide(10, 0)) // 0 (после восстановления)
fmt.Println("Program continues")
}
Пример 3: Разные типы паники
package main
import "fmt"
func handlePanic() {
if r := recover(); r != nil {
switch v := r.(type) {
case string:
fmt.Println("String panic:", v)
case error:
fmt.Println("Error panic:", v)
default:
fmt.Printf("Unknown panic: %v (%T)\n", v, v)
}
}
}
func main() {
defer handlePanic()
// Можно раскомментировать любой вариант:
panic("string panic")
// panic(fmt.Errorf("error panic"))
// panic(42)
}
Пример 4: recover в горутинах
package main
import (
"fmt"
"time"
)
func worker(id int) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Worker %d recovered: %v\n", id, r)
}
}()
if id == 2 {
panic(fmt.Sprintf("panic in worker %d", id))
}
fmt.Printf("Worker %d working\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(time.Second) // Даем время горутинам завершиться
}
Пример 5: Вложенные recover
package main
import "fmt"
func inner() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Inner recovered:", r)
}
}()
panic("inner panic")
}
func outer() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Outer recovered:", r)
}
}()
inner()
fmt.Println("This won't be executed")
}
func main() {
outer()
fmt.Println("Program continues")
}
Важные замечания:
recover()
работает только внутри defer-функций
- Каждый вызов
recover()
обрабатывает только одну панику
- После восстановления выполнение продолжается после блока defer
- В Go 1.21+
recover()
возвращает nil только если паники не было
- Не злоупотребляйте recover - используйте только для действительно неожиданных ошибок
2 - Типы в пакете builtin
Описание типов из пакета builtin
type ComplexType
type ComplexType complex64
ComplexType используется здесь исключительно в целях документирования. Он заменяет любой из типов complex: complex64 или complex128.
type FloatType
FloatType используется здесь исключительно в целях документирования. Он заменяет любой из типов float: float32 или float64.
type IntegerType
IntegerType используется здесь только в целях документирования. Он заменяет любой тип целого числа: int, uint, int8 и т. д.
type Type
Type используется здесь только в целях документирования. Он заменяет любой тип Go, но представляет один и тот же тип для любого вызова функции.
type Type1
Type1 используется здесь только в целях документирования. Он является заменителем для любого типа Go, но представляет один и тот же тип для любого вызова функции.
type any
any является псевдонимом для interface{} и во всех отношениях эквивалентен interface{}.
type bool
bool — это набор булевых значений true и false.
type byte
byte — это псевдоним для uint8 и во всех отношениях эквивалентен uint8. По соглашению он используется для отличия значений byte от 8-битных целых чисел без знака.
type comparable
type comparable interface{ comparable }
comparable
— это интерфейс, который реализуется всеми сопоставимыми типами (булевыми значениями, числами, строками, указателями, каналами, массивами сопоставимых типов, структурами, все поля которых являются сопоставимыми типами). Интерфейс comparable
может использоваться только в качестве ограничения параметра типа, а не в качестве типа переменной.
Подробнее
Интерфейс comparable
- это специальный встроенный интерфейс в Go, который представляет все типы, поддерживающие операции сравнения ==
и !=
. Он используется исключительно как ограничение (constraint) для параметров типа в дженериках.
Особенности comparable
:
- Неявная реализация - все сопоставимые типы автоматически удовлетворяют этому интерфейсу
- Ограниченное использование - может применяться только как ограничение типа в дженериках
- Строгая типизация - гарантирует, что типы можно сравнивать между собой
Пример 1: Простая функция сравнения
package main
import "fmt"
// Equal проверяет равенство двух значений comparable типа
func Equal[T comparable](a, b T) bool {
return a == b
}
func main() {
fmt.Println(Equal(1, 1)) // true
fmt.Println(Equal("a", "b")) // false
fmt.Println(Equal(true, false)) // false
}
Пример 2: Проверка наличия элемента в слайсе
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
func main() {
nums := []int{1, 2, 3}
fmt.Println(Contains(nums, 2)) // true
fmt.Println(Contains(nums, 5)) // false
strs := []string{"a", "b", "c"}
fmt.Println(Contains(strs, "b")) // true
}
Пример 3: Уникальные элементы в слайсе
func Unique[T comparable](slice []T) []T {
seen := make(map[T]bool)
result := []T{}
for _, v := range slice {
if !seen[v] {
seen[v] = true
result = append(result, v)
}
}
return result
}
func main() {
dupes := []int{1, 2, 2, 3, 4, 4, 5}
fmt.Println(Unique(dupes)) // [1 2 3 4 5]
}
Какие типы являются comparable
:
- Базовые типы:
bool
, int
, float64
, string
и т.д.
- Указатели (
*T
)
- Каналы (
chan T
)
- Массивы, если их элементы comparable (
[3]int
, [2]string
)
- Структуры, если все их поля comparable
Какие типы НЕ являются comparable
:
- Слайсы (
[]T
)
- Мапы (
map[K]V
)
- Функции
- Структуры, содержащие несопоставимые поля
Пример 4: Ошибка при использовании несопоставимого типа
func main() {
// Ошибка: slice does not satisfy comparable
fmt.Println(Equal([]int{1}, []int{1}))
// Ошибка: map does not satisfy comparable
fmt.Println(Equal(map[int]int{}, map[int]int{}))
}
Практическое применение:
- Создание универсальных контейнеров
- Реализация алгоритмов для разных типов
- Написание тестовых утилит
- Создание библиотечных функций
type complex128
type complex128 complex128
complex128 — это набор всех комплексных чисел с вещественными и мнимыми частями float64.
type complex64
complex64 — это набор всех комплексных чисел с вещественными и мнимыми частями типа float32.
type error
type error интерфейс {
Error() string
}
Встроенный интерфейсный тип error — это стандартный интерфейс для представления условия ошибки, причем значение nil означает отсутствие ошибки.
type float32
float32 — это набор всех 32-разрядных чисел с плавающей запятой IEEE 754.
type float64
float64 — это набор всех 64-разрядных чисел с плавающей запятой IEEE 754.
type int
int — это тип целых чисел с знаком, размер которого составляет не менее 32 бит. Однако это отдельный тип, а не псевдоним, например, int32.
type int16
int16 — это набор всех 16-разрядных целых чисел со знаком. Диапазон: от -32768 до 32767.
type int32
int32 — это набор всех 32-разрядных целых чисел со знаком. Диапазон: от -2147483648 до 2147483647.
type int64
int64 — это набор всех 64-разрядных целых чисел со знаком. Диапазон: от -9223372036854775808 до 9223372036854775807.
type int8
int8 — это набор всех 8-битных целых чисел со знаком. Диапазон: от -128 до 127.
type rune
rune — это псевдоним для int32 и во всех отношениях эквивалентен int32. По соглашению он используется для отличия значений символов от целочисленных значений.
type string
string — это набор всех строк из 8-битных байтов, которые по соглашению, но не обязательно, представляют текст, закодированный в UTF-8. Строка может быть пустой, но не может быть nil. Значения типа string являются неизменяемыми.
type uint
uint — это тип целого числа без знака, размер которого составляет не менее 32 бит. Однако это отдельный тип, а не псевдоним, например, для uint32.
type uint16
uint16 — это набор всех 16-битных целых чисел без знака. Диапазон: от 0 до 65535.
type uint32
uint32 — это набор всех 32-битных целых чисел без знака. Диапазон: от 0 до 4294967295.
type uint64
uint64 — это набор всех 64-разрядных целых чисел без знака. Диапазон: от 0 до 18446744073709551615.
type uint8
uint8 — это набор всех 8-разрядных целых чисел без знака. Диапазон: от 0 до 255.
type uintptr
uintptr — это целочисленный тип, который достаточно велик, чтобы содержать битовую матрицу любого указателя.