Last active
August 23, 2025 10:09
-
-
Save skillissueru/0e4bbf95880dfc2299d0714b3ca17873 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "context" | |
| "errors" | |
| "fmt" | |
| "math/rand" | |
| "sync" | |
| "time" | |
| ) | |
| // Более оптимальное решение задачи из этого видео: | |
| // https://youtu.be/wZCLVt_5-4c | |
| // Из сигнатуры функции processData убран кастомный тип + убран один селект | |
| // (он не был прям сильно лишним, но от него можно избавиться +- безболезненно) | |
| // условие задачи: | |
| // реализовать функцию processParallel | |
| // прокинуть контекст | |
| var errTimeout = errors.New("timed out") | |
| func processData(ctx context.Context, v int) (int, error) { | |
| ch := make(chan struct{}) | |
| go func() { | |
| time.Sleep(time.Duration(rand.Intn(10)) * time.Second) | |
| close(ch) | |
| }() | |
| select { | |
| case <-ch: | |
| case <-ctx.Done(): | |
| return 0, errTimeout | |
| } | |
| return v * 2, nil | |
| } | |
| func main() { | |
| in := make(chan int) | |
| out := make(chan int) | |
| ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | |
| defer cancel() | |
| go func() { | |
| defer close(in) | |
| for i := range 10 { | |
| select { | |
| case in <- i + 1: | |
| case <-ctx.Done(): | |
| return | |
| } | |
| } | |
| }() | |
| start := time.Now() | |
| processParallel(ctx, in, out, 5) | |
| for v := range out { | |
| fmt.Println("v =", v) | |
| } | |
| fmt.Println("main duration:", time.Since(start)) | |
| } | |
| func processParallel(ctx context.Context, in <-chan int, out chan<- int, numWorkers int) { | |
| wg := &sync.WaitGroup{} | |
| for range numWorkers { | |
| wg.Add(1) | |
| go worker(ctx, in, out, wg) | |
| } | |
| go func() { | |
| wg.Wait() | |
| close(out) | |
| }() | |
| } | |
| func worker(ctx context.Context, in <-chan int, out chan<- int, wg *sync.WaitGroup) { | |
| defer wg.Done() | |
| for { | |
| select { | |
| case v, ok := <-in: | |
| if !ok { | |
| return | |
| } | |
| val, err := processData(ctx, v) | |
| if errors.Is(err, errTimeout) { | |
| return | |
| } | |
| //...handle other error types | |
| select { | |
| case <-ctx.Done(): | |
| return | |
| case out <- val: | |
| } | |
| case <-ctx.Done(): | |
| return | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
здравствуйте! только изучаю голанг, у вас крутые видосы, спасибо за них! пытаюсь прикинуть можно ли сделать поменьше кода и по-возможности поменьше менять написанного от изначального в задаче
многие в комментах к видео говорили о том, что неочевидно (что надо) и непрактично менять сигнатуру processData(), потому что она может использоваться где-то еще
не будет оптимальнее применить паттерн генератор в обертке над функцией, куда прокинуть сам контекст?
и тогда воркер, по идее, будет станет просто
или я что-то упустил?
нужен ли в таком варианте в воркере, если мы попали в processedDataWithTimeout вот этот кусок?
ведь если контекст истек внутри processDataWithTimeout или одновременно случился и кейс чтения из in и истечения контекста, то из processDataWithTimeout вернется false и мы просто выйдем, следовательно запись в канал out дальше относительно безопасна и как будто можно сократить до