Александър обнови решението на 29.11.2016 15:57 (преди над 1 година)
+package main
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// ############ TASK 1 #############
+
+type Task interface {
+ Execute(int) (int, error)
+}
+type adder struct {
+ augend int
+}
+type executor struct {
+ tasks []Task
+}
+
+func (ex executor) Execute(number int) (int, error) {
+ var result int
+ var err error
+ if len(ex.tasks) == 0 {
+ return 0, errors.New("some err")
+ }
+ for i, task := range ex.tasks {
+ if i == 0 {
+ result, err = task.Execute(number)
+ } else {
+ result, err = task.Execute(result)
+ }
+ if err != nil {
+ return 0, errors.New("some err")
+ }
+ }
+ return result, nil
+}
+func (a adder) Execute(addend int) (int, error) {
+ result := a.augend + addend
+ if result > 127 {
+ return 0, fmt.Errorf("Result %d exceeds the adder threshold", a)
+ }
+ return result, nil
+}
+func Pipeline(tasks ...Task) Task {
+ return &executor{tasks}
+}
+
+// ############ TASK 2 #############
+type lazyAdder struct {
+ adder
+ delay time.Duration
+}
+type executor2 struct {
+ tasks []Task
+}
+
+func (ex executor2) Execute(number int) (int, error) {
+ if len(ex.tasks) == 0 {
+ return 0, errors.New("some err")
+ }
+ c := make(chan int, len(ex.tasks))
+
+ for _, task := range ex.tasks {
+ go func() {
+ res, _ := task.Execute(number)
+ c <- res
+ }()
+ }
+ return <-c, nil
+}
+func (la lazyAdder) Execute(addend int) (int, error) {
+ time.Sleep(la.delay * time.Millisecond)
+ return la.adder.Execute(addend)
+}
+func Fastest(tasks ...Task) Task {
+ return &executor2{tasks}
+}
+
+// ############ TASK 3 #############
+type executor3 struct {
+ task Task
+ timeout time.Duration
+}
+
+func (ex executor3) Execute(number int) (int, error) {
+ type result struct {
+ res int
+ err error
+ }
+ c := make(chan result, 1)
+ go func() {
+ res, err := ex.task.Execute(number)
+ c <- result{res, err}
+ }()
+ select {
+ case res := <-c:
+ if res.err != nil {
+ return res.res, nil
+ }
+ return 0, res.err
+ case <-time.After(ex.timeout):
+ return 0, errors.New("some timeout err")
+ }
+ return 0, nil
+}
+func Timed(task Task, timeout time.Duration) Task {
+ return &executor3{task, timeout}
+}
+
+// ############ TASK 4 #############
+type executor4 struct {
+ tasks []Task
+ f func([]int) int
+}
+
+func (ex executor4) Execute(number int) (int, error) {
+ if len(ex.tasks) == 0 {
+ return 0, errors.New("some err")
+ }
+ type result struct {
+ res int
+ err error
+ }
+ c := make(chan result, len(ex.tasks))
+ var wg sync.WaitGroup
+ wg.Add(len(ex.tasks))
+ for _, task := range ex.tasks {
+ go func() {
+ res, err := task.Execute(number)
+ c <- result{res, err}
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ close(c)
+ results := make([]int, 0)
+ for res := range c {
+ results = append(results, res.res)
+ if res.err != nil {
+ return 0, errors.New("big error here")
+ }
+ }
+ return ex.f(results), nil
+}
+func ConcurrentMapReduce(reduce func(results []int) int, tasks ...Task) Task {
+ return &executor4{tasks, reduce}
+}
+
+// ############ TASK 5 #############
+// NOT DONE
+type executor5 struct {
+}
+
+func (ex executor5) Execute(number int) (int, error) {
+ return 0, nil
+}
+func GreatestSearcher(errorLimit int, tasks <-chan Task) Task {
+ return &executor5{}
+}