Skip to content

Commit 381ffff

Browse files
new example
1 parent f0aa11e commit 381ffff

File tree

1 file changed

+75
-90
lines changed

1 file changed

+75
-90
lines changed
Lines changed: 75 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,108 @@
11
package main
22

33
import (
4-
"context"
5-
"errors"
6-
"fmt"
7-
"time"
4+
"database/sql"
5+
"log"
86
)
97

108
// =============================================================================
119

12-
// This code defined a concrete type named user with a name and email field.
13-
14-
type user struct {
15-
name string
16-
email string
10+
type User struct {
11+
ID int64
12+
Name string
13+
Email string
1714
}
1815

19-
// =============================================================================
20-
21-
// WorkerInterface defines a function signature that takes a context value as
22-
// input and returns any value (via the empty interface) and an error.
23-
//
24-
// The retryInterface function provides functionality to execute a worker
25-
// function and if it fails, calls it again until the context times out. The
26-
// function returns back to the caller the values returned from the worker
27-
// function.
28-
29-
type WorkerInterface func(ctx context.Context) (interface{}, error)
16+
func InsertUser(db *sql.DB, u User) (User, error) {
17+
const query = "insert into users (name, email) values ($1, $2)"
18+
result, err := ExecuteQuery(query, u.Name, u.Email)
19+
if err != nil {
20+
return User{}, err
21+
}
3022

31-
func retryInterface(ctx context.Context, interval time.Duration, worker WorkerInterface) (interface{}, error) {
32-
if ctx.Err() != nil {
33-
return nil, errors.New("error")
23+
id, err := result.LastInsertId()
24+
if err != nil {
25+
return User{}, err
3426
}
3527

36-
var retry *time.Timer
28+
u.ID = id
29+
return u, nil
30+
}
3731

38-
for {
39-
if value, err := worker(ctx); err == nil {
40-
return value, nil
41-
}
32+
type Customer struct {
33+
ID int64
34+
Name string
35+
Email string
36+
}
4237

43-
if retry == nil {
44-
retry = time.NewTimer(interval)
45-
}
38+
func InsertCustomer(db *sql.DB, c Customer) (Customer, error) {
39+
const query = "insert into customers (name, email) values ($1, $2)"
40+
result, err := ExecuteQuery(query, c.Name, c.Email)
41+
if err != nil {
42+
return Customer{}, err
43+
}
4644

47-
select {
48-
case <-ctx.Done():
49-
retry.Stop()
50-
return nil, errors.New("error")
51-
case <-retry.C:
52-
retry.Reset(interval)
53-
}
45+
id, err := result.LastInsertId()
46+
if err != nil {
47+
return Customer{}, err
5448
}
49+
50+
c.ID = id
51+
return c, nil
5552
}
5653

5754
// =============================================================================
5855

59-
// This is a generics version of the last example.
60-
//
61-
// WorkerGeneric defines a function signature that takes a context value as
62-
// input and returns any value of type Result (to be determined at compile time)
63-
// and an error.
64-
//
65-
// The retryGeneric function provides functionality to execute a worker
66-
// function and if it fails, calls it again until the context times out. The
67-
// function returns back to the caller the values returned from the worker
68-
// function. In this case, the returned values are based on type Result and not
69-
// the empty interface.
70-
//
71-
// Returning zero value is an interesting aspect of this code. A variable
72-
// named zero of type Result is constructed at the return site and used for the
73-
// return statement.
74-
75-
type WorkerGeneric(type Result) func(ctx context.Context) (Result, error)
76-
77-
func retryGeneric(type Result)(ctx context.Context, interval time.Duration, worker WorkerGeneric(Result)) (Result, error) {
78-
if ctx.Err() != nil {
79-
var zero Result
80-
return zero, errors.New("error")
56+
type inserter interface {
57+
type User, Customer
58+
}
59+
60+
func Insert(type T inserter)(db *sql.DB, entity T, query string, args ...interface{}) (T, error) {
61+
var zero T
62+
63+
result, err := ExecuteQuery(query, args...)
64+
if err != nil {
65+
return zero, err
8166
}
8267

83-
var retry *time.Timer
84-
85-
for {
86-
if value, err := worker(ctx); err == nil {
87-
return value, nil
88-
}
89-
90-
if retry == nil {
91-
retry = time.NewTimer(interval)
92-
}
93-
94-
select {
95-
case <-ctx.Done():
96-
retry.Stop()
97-
var zero Result
98-
return zero, errors.New("error")
99-
case <-retry.C:
100-
retry.Reset(interval)
101-
}
68+
id, err := result.LastInsertId()
69+
if err != nil {
70+
return zero, err
10271
}
72+
73+
entity.ID = id
74+
return entity, nil
75+
}
76+
77+
// =============================================================================
78+
79+
type Result struct{}
80+
81+
func (r Result) LastInsertId() (int64, error) { return 1, nil }
82+
func (r Result) RowsAffected() (int64, error) { return 1, nil }
83+
84+
func ExecuteQuery(query string, args ...interface{}) (sql.Result, error) {
85+
return Result{}, nil
10386
}
10487

10588
// =============================================================================
10689

10790
func main() {
108-
ctx := context.Background()
91+
var db *sql.DB
10992

110-
workerInt := func(ctx context.Context) (interface{}, error) {
111-
time.Sleep(time.Millisecond)
112-
return &user{"bill", "[email protected]"}, nil
93+
var u User
94+
query := "insert into users (name, email) values ($1, $2)"
95+
u, err := Insert(db, u, query, u.Name, u.Email)
96+
if err != nil {
97+
log.Fatal(err)
11398
}
114-
intf, err := retryInterface(ctx, time.Second, workerInt)
115-
fmt.Println(intf.(*user), err)
99+
log.Println(u)
116100

117-
workerGen := func(ctx context.Context) (*user, error) {
118-
time.Sleep(time.Millisecond)
119-
return &user{"bill", "[email protected]"}, nil
101+
var c Customer
102+
query := "insert into customers (name, email) values ($1, $2)"
103+
c, err := Insert(db, c, query, u.Name, u.Email)
104+
if err != nil {
105+
log.Fatal(err)
120106
}
121-
user, err := retryGeneric(*user)(ctx, time.Second, workerGen)
122-
fmt.Println(user, err)
107+
log.Println(c)
123108
}

0 commit comments

Comments
 (0)