forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 0
/
example2.go
137 lines (106 loc) · 2.72 KB
/
example2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
// Sample program demonstrating decoupling with interfaces.
package main
import (
"errors"
"fmt"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// =============================================================================
// EOD represents the end of the data stream.
var EOD = errors.New("EOD")
// Data is the structure of the data we are copying.
type Data struct {
Line string
}
// =============================================================================
// Puller declares behavior for pulling data.
type Puller interface {
Pull(d *Data) error
}
// Storer declares behavior for storing data.
type Storer interface {
Store(d Data) error
}
// =============================================================================
// Xenia is a system we need to pull data from.
type Xenia struct{}
// Pull knows how to pull data out of Xenia.
func (Xenia) Pull(d *Data) error {
switch rand.Intn(10) {
case 1, 9:
return EOD
case 5:
return errors.New("Error reading data from Xenia")
default:
d.Line = "Data"
fmt.Println("In:", d.Line)
return nil
}
}
// Pillar is a system we need to store data into.
type Pillar struct{}
// Store knows how to store data into Pillar.
func (Pillar) Store(d Data) error {
fmt.Println("Out:", d.Line)
return nil
}
// =============================================================================
// System wraps Xenia and Pillar together into a single system.
type System struct {
Xenia
Pillar
}
// =============================================================================
// IO provides support to copy bulk data.
type IO struct{}
// pull knows how to pull bulks of data from any Puller.
func (IO) pull(p Puller, data []Data) (int, error) {
for i := range data {
if err := p.Pull(&data[i]); err != nil {
return i, err
}
}
return len(data), nil
}
// store knows how to store bulks of data from any Storer.
func (IO) store(s Storer, data []Data) error {
for _, d := range data {
if err := s.Store(d); err != nil {
return err
}
}
return nil
}
// Copy knows how to pull and store data from the System.
func (io IO) Copy(sys *System, batch int) error {
for {
data := make([]Data, batch)
i, err := io.pull(&sys.Xenia, data)
if i > 0 {
if err := io.store(&sys.Pillar, data[:i]); err != nil {
return err
}
}
if err != nil {
return err
}
}
}
// =============================================================================
func main() {
// Initialize the system for use.
sys := System{
Xenia: Xenia{},
Pillar: Pillar{},
}
var io IO
if err := io.Copy(&sys, 3); err != EOD {
fmt.Println(err)
}
}