Встречается на 16% собеседований по Go

Какие бывают типы в Go

В Go типы делятся на четыре основные категории: базовые (скалярные), агрегированные (составные), ссылочные и интерфейсы. Базовые типы включают числа, строки и булевы значения; агрегированные — массивы, срезы и структуры; ссылочные — указатели, карты и функции; интерфейсы задают набор методов. Понимание этой классификации помогает выбирать подходящий тип для данных и эффективно управлять памятью.

Базовые типы

Базовые типы — это простые значения, которые хранятся непосредственно в переменной.

  • Числовые типы: целые (int, int8, int16, int32, int64, а также беззнаковые uint, uint8, uint16, uint32, uint64), числа с плавающей запятой (float32, float64) и комплексные (complex64, complex128).
  • Булев тип: bool со значениями true и false.
  • Строки: string — неизменяемая последовательность байт, обычно для текста.
  • Символьные типы: byte (алиас uint8) и rune (алиас int32, представляет Unicode-символ).

Агрегированные типы

Агрегированные типы объединяют несколько значений в одну переменную.

  • Массивы: фиксированная длина, например [5]int.
  • Срезы: динамическая длина, например []int. Срез — это ссылка на массив, но в отличие от массива его длина может меняться.
  • Структуры: набор именованных полей, например type Person struct { Name string; Age int }.

Ссылочные типы

Ссылочные типы хранят ссылку на данные, а не сами данные. При присваивании копируется ссылка, а не значение.

  • Указатели: *T — хранит адрес переменной типа T. Позволяет изменять значение по ссылке.
  • Карты: map[K]V — неупорядоченная коллекция пар «ключ-значение», например map[string]int.
  • Функции: тип функции задаётся сигнатурой, например func(int) int. Функции можно передавать как аргументы и возвращать из других функций.

Интерфейсы

Интерфейс определяет набор методов, которые должен реализовать тип, чтобы считаться удовлетворяющим интерфейсу. Например, type Stringer interface { String() string }. Пустой интерфейс interface{} (или any в Go 1.18+) может хранить значение любого типа.

Пример использования разных типов

go
package main

import "fmt"

// Структура
type Person struct {
    Name string
    Age  int
}

// Реализация интерфейса Stringer
func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    // Базовые типы
    var age int = 30
    var name string = "Alice"
    var isStudent bool = false

    // Агрегированные типы
    var scores [3]int = [3]int{90, 85, 88}
    var people []Person = []Person{
        {Name: "Bob", Age: 25},
        {Name: "Charlie", Age: 35},
    }

    // Ссылочные типы
    var p *Person = &Person{Name: "Dave", Age: 40}
    var ageMap map[string]int = map[string]int{"Alice": 30, "Bob": 25}

    // Вывод
    fmt.Println("Name:", name)
    fmt.Println("Age:", age)
    fmt.Println("Is student:", isStudent)
    fmt.Println("Scores:", scores)
    fmt.Println("People:", people)
    fmt.Println("Pointer to Person:", p)
    fmt.Println("Age map:", ageMap)
}

Подводные камни

  • int и uint имеют платформозависимый размер (32 или 64 бита). Для точного размера используйте int32 или int64.
  • Срезы и карты — ссылочные типы, но при передаче в функцию копируется заголовок, а не данные. Изменения внутри функции видны снаружи.
  • byte и rune — это алиасы, но их использование улучшает читаемость: byte для байтов, rune для Unicode-символов.
  • Пустой интерфейс interface{} удобен, но злоупотребление им снижает типобезопасность. В Go 1.18+ можно использовать any как синоним.

Коротко

  • Типы Go делятся на базовые, агрегированные, ссылочные и интерфейсы.
  • Базовые: числа, строки, bool, byte, rune.
  • Агрегированные: массивы, срезы, структуры.
  • Ссылочные: указатели, карты, функции; интерфейсы задают поведение через методы.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы