Практическая задача: разбор кода go

В представленном коде есть несколько проблем, связанных с использованием каналов и горутин:

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

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

В представленном коде есть несколько проблем, связанных с использованием каналов и горутин:

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

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

Условие

package main

func main() {
    nums := make(chan int, 10)

    for i := 0; i < 10; i++ {
        nums <- i
    }
    close(nums)

    for i := 0; i < 3; i++ {
        go sqare(nums)
    }
}

func sqare(nums <-chan int) <-chan int {
    res := make(chan int, 10)
    for n := range nums {
        res <- n * n
    }

    return res
}

Ответ

В представленном коде есть несколько проблем, связанных с использованием каналов и горутин:

  1. Функция sqare (вероятно, опечатка, должно быть square) принимает на вход канал nums и создаёт новый канал res, в который записывает квадраты чисел. Но при этом функция возвращает res, однако в main этот возвращаемый канал никак не используется.
  2. В main запускаются 3 горутины sqare(nums), которые одновременно читают из одного и того же канала nums. Это может привести к тому, что каждый элемент будет обработан только одной горутиной, что, возможно, и ожидается.
  3. Однако, поскольку res создаётся внутри каждой горутины и не передаётся наружу, результаты вычислений теряются.

Чтобы исправить код и получить квадраты чисел, можно сделать так:

  • Создать один выходной канал res в main.
  • Передать его в горутины для записи результатов.
  • В main считать из res результаты.

Пример исправленного кода:

package main

import (
    "fmt"
    "sync"
)

func main() {
    nums := make(chan int, 10)
    res := make(chan int, 10)

    for i := 0; i < 10; i++ {
        nums <- i
    }
    close(nums)

    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            square(nums, res)
        }()
    }

    go func() {
        wg.Wait()
        close(res)
    }()

    for val := range res {
        fmt.Println(val)
    }
}

func square(nums <-chan int, res chan<- int) {
    for n := range nums {
        res <- n * n
    }
}

В этом варианте три горутины параллельно читают из nums, вычисляют квадрат и пишут в общий канал res. После завершения всех горутин канал res закрывается, и main выводит все результаты.

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

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

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

Подробнее