Оптимизация и рефакторинг существующего Go‑кода

Главный перерасход памяти вызван возвратом маленького слайса, удерживающего массив на 100 000 элементов. Скопируйте последний элемент в отдельный слайс или вычислите его напрямую.

Короткий ответ

Что ответить на собеседовании

Главный перерасход памяти вызван возвратом маленького слайса, удерживающего массив на 100 000 элементов. Скопируйте последний элемент в отдельный слайс или вычислите его напрямую.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо выполнить рефакторинг представленного фрагмента программы на Go. Задача подразумевает улучшение читаемости и структуры кода, а также возможную оптимизацию использования памяти. При этом следует оставить всю функциональность без изменений.

func main() {
    var mem runtime.MemStats

    runtime.ReadMemStats(&mem)
    fmt.Printf("Before get(): Alloc = %v MiB\n", mem.Alloc/1024/1024)

    resOfRes := make([][]int, 0, 100)

    for i := 0; i < 50; i++ {
        res := getLastElem()

        runtime.GC()
        runtime.ReadMemStats(&mem)
        fmt.Printf("After getAll(): Alloc = %v MiB, slice: %v\n", mem.Alloc/1024/1024, res)

        resOfRes = append(resOfRes, res)
    }

    fmt.Println()
    _ = resOfRes

    // Now go into loop
    for i := 0; i < 20000; i++ {
        runtime.GC()
        runtime.ReadMemStats(&mem)
        fmt.Printf("Alloc = %v MiB\n", mem.Alloc/1024/1024)
        time.Sleep(time.Second * 2)
    }

    fmt.Println(resOfRes)
}

func getLastElem() []int {
    sl := make([]int, 0, 100000)

    for i := 0; i < 100000; i++ {
        sl = append(sl, i)
    }

    // return last element
    return sl[99999:]
}

В рамках рефакторинга следует обратить внимание на:

  • Выделение повторяющихся операций в отдельные функции;
  • Улучшение именования переменных и функций для повышения самодокументируемости кода;
  • Уменьшение количества прямых вызовов сборщика мусора и измерений памяти, если это не требуется для демонстрации;
  • Возможное использование более эффективных способов создания и работы со срезами.

Ответ

Главный перерасход памяти вызван возвратом маленького слайса, удерживающего массив на 100 000 элементов. Скопируйте последний элемент в отдельный слайс или вычислите его напрямую.

При сохранении демонстрационного построения массива верните []int{sl[len(sl)-1]} вместо sl[99999:]. Для точно заданной генерации 0–99999 функционально достаточно return []int{99999}. Ограничение capacity старого среза не освобождает массив. Повтор измерения вынесите в helper; принудительные GC оставляйте только для эксперимента, а не оптимизации рабочего сервиса. resOfRes используется в конце и удерживает все возвращённые массивы.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее