forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 0
/
example4.go
137 lines (107 loc) · 2.69 KB
/
example4.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 interface composition.
package main
import (
"errors"
"fmt"
"io"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// =============================================================================
// 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
}
// PullStorer declares behavior for both pulling and storing.
type PullStorer interface {
Puller
Storer
}
// =============================================================================
// 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 io.EOF
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 Pullers and Stores together into a single system.
type System struct {
Puller
Storer
}
// =============================================================================
// pull knows how to pull bulks of data from any Puller.
func 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 store(s Storer, data []Data) (int, error) {
for i, d := range data {
if err := s.Store(d); err != nil {
return i, err
}
}
return len(data), nil
}
// Copy knows how to pull and store data from any System.
func Copy(ps PullStorer, batch int) error {
data := make([]Data, batch)
for {
i, err := pull(ps, data)
if i > 0 {
if _, err := store(ps, data[:i]); err != nil {
return err
}
}
if err != nil {
return err
}
}
}
// =============================================================================
func main() {
// Initialize the system for use.
sys := System{
Puller: Xenia{},
Storer: Pillar{},
}
if err := Copy(&sys, 3); err != io.EOF {
fmt.Println(err)
}
}