Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions homeworks/15_contexts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# # Домашнее задание №15

**В домашнем задании нужно реализовать err group.**

**Err group** - это паттерн/подход в языке программирования Go, представляющий собой группу горутин, которые работают вместе для достижения общей цели. Он обеспечивает простой и эффективный способ отслеживания ошибок, возникающих в любое время.

API для err group будет выглядеть следующим образом:

```go
type Group struct { ... }

func NewErrGroup(ctx context.Context)
func (g *Group) Go(action func() error)
func (g *Group) Wait() error
```

Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по [ссылке](https://github.com/Balun-courses/deep_go/blob/master/homework/contexts/homework_test.go).

42 changes: 42 additions & 0 deletions homeworks/15_contexts/homework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package homework15

import (
"context"
"sync"
)

type Group struct {
ctx context.Context
cancel context.CancelFunc
wg sync.WaitGroup
once sync.Once
err error
}

func NewErrGroup(ctx context.Context) (*Group, context.Context) {
contex, cancel := context.WithCancel(ctx)
return &Group{
ctx: contex,
cancel: cancel,
}, contex
}

func (g *Group) Go(action func() error) {
g.wg.Add(1)

go func() {
defer g.wg.Done()
if err := action(); err != nil {
g.once.Do(func() {
g.cancel()
g.err = err
})
}

}()
}

func (g *Group) Wait() error {
g.wg.Wait()
return g.err
}
56 changes: 56 additions & 0 deletions homeworks/15_contexts/homework_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package homework15

import (
"context"
"errors"
"sync/atomic"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestErrGroupWithoutError(t *testing.T) {
var counter atomic.Int32
group, _ := NewErrGroup(context.Background())

for i := 0; i < 5; i++ {
group.Go(func() error {
time.Sleep(time.Second)
counter.Add(1)
return nil
})
}

err := group.Wait()
assert.Equal(t, int32(5), counter.Load())
assert.NoError(t, err)
}

func TestErrGroupWithError(t *testing.T) {
var counter atomic.Int32
group, ctx := NewErrGroup(context.Background())

for i := 0; i < 5; i++ {
group.Go(func() error {
timer := time.NewTimer(time.Second)
defer timer.Stop()

select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
counter.Add(1)
return nil
}
})
}

group.Go(func() error {
return errors.New("error")
})

err := group.Wait()
assert.Equal(t, int32(0), counter.Load())
assert.Error(t, err)
}