Есть функция `unpredictableFunc()`, нужно обернуть её так, чтобы она выполнялась с таймаутом (например, 1 секунда), и логировалось время выполнения.

Ниже пример функции-обёртки в Go, которая запускает переданную функцию с таймаутом 1 секунду, измеряет время выполнения и возвращает ошибку, если время вышло:

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

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

Ниже пример функции-обёртки в Go, которая запускает переданную функцию с таймаутом 1 секунду, измеряет время выполнения и возвращает ошибку, если время вышло:

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

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

Условие

Есть функция unpredictableFunc(), нужно обернуть её так, чтобы она выполнялась с таймаутом (например, 1 секунда), и логировалось время выполнения.

// Есть функция, работающая неопределённо долго и возвращающая число. // Её тело нельзя изменять (представим, что внутри сетевой запрос). func unpredictableFunc() int64 { rnd := rand.Int63n(5000) time.Sleep(time.Duration(rnd) * time.Millisecond)

return rnd

}

// Нужно изменить функцию обёртку, которая будет работать с заданным таймаутом (например, 1 секунду). // Если "длинная" функция отработала за это время - отлично, возвращаем результат. // Если нет - возвращаем ошибку. Результат работы в этом случае нам не важен. // // Дополнительно нужно измерить, сколько выполнялась эта функция (просто вывести в лог). // Сигнатуру функцию обёртки менять можно. func predictableFunc() int64 { return unpredictableFunc() }

Ответ

Ниже пример функции-обёртки в Go, которая запускает переданную функцию с таймаутом 1 секунду, измеряет время выполнения и возвращает ошибку, если время вышло:

package main

import (
    "errors"
    "log"
    "time"
)

// TimeoutWrapper запускает функцию fn с таймаутом timeout
func TimeoutWrapper(fn func() (interface{}, error), timeout time.Duration) (interface{}, error) {
    start := time.Now()
    resultChan := make(chan interface{})
    errChan := make(chan error)

    go func() {
        res, err := fn()
        if err != nil {
            errChan <- err
            return
        }
        resultChan <- res
    }()

    select {
    case res := <-resultChan:
        elapsed := time.Since(start)
        log.Printf("Function completed in %v", elapsed)
        return res, nil
    case err := <-errChan:
        elapsed := time.Since(start)
        log.Printf("Function errored in %v", elapsed)
        return nil, err
    case <-time.After(timeout):
        elapsed := time.Since(start)
        log.Printf("Function timed out after %v", elapsed)
        return nil, errors.New("function timed out")
    }
}

// Пример "длинной" функции
func longFunc() (interface{}, error) {
    time.Sleep(2 * time.Second) // имитация долгой работы
    return "done", nil
}

func main() {
    res, err := TimeoutWrapper(longFunc, 1*time.Second)
    if err != nil {
        log.Println("Error:", err)
    } else {
        log.Println("Result:", res)
    }
}

В этом примере функция TimeoutWrapper запускает переданную функцию в горутине, ждёт её результат или ошибку, либо таймаут. Время выполнения логируется в любом случае.

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

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

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

Подробнее