Skip to content

Commit

Permalink
[1113] section73
Browse files Browse the repository at this point in the history
  • Loading branch information
myeunee committed Nov 12, 2024
1 parent 741e4f9 commit 19c1390
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 6 deletions.
21 changes: 21 additions & 0 deletions chapter18/section72/clock/clock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package clock

import (
"time"
)

type Clocker interface {
Now() time.Time
}

type RealClocker struct{}

func (r RealClocker) Now() time.Time {
return time.Now()
}

type FixedClocker struct{}

func (fc FixedClocker) Now() time.Time {
return time.Date(2022, 5, 10, 12, 34, 56, 0, time.UTC)
}
9 changes: 7 additions & 2 deletions chapter18/section72/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import (
)

type Config struct {
Env string `env:"TODO_ENV" envDefault:"dev"`
Port int `env:"PORT" envDefault:"80"`
Env string `env:"TODO_ENV" envDefault:"dev"`
Port int `env:"PORT" envDefault:"80"`
DBHost string `env:"TODO_DB_HOST" envDefault:"127.0.0.1"`
DBPort int `env:"TODO_DB_PORT" envDefault:"33306"`
DBUser string `env:"TODO_DB_USER" envDefault:"todo"`
DBPassword string `env:"TODO_DB_PASSWORD" envDefault:"todo"`
DBName string `env:"TODO_DB_NAME" envDefault:"todo"`
}

func New() (*Config, error) {
Expand Down
9 changes: 5 additions & 4 deletions chapter18/section72/entity/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ const (
)

type Task struct {
ID TaskID `json:"id"`
Title string `json:"title"`
Status TaskStatus `json:"status" `
Created time.Time `json:"created"`
ID TaskID `json:"id"`
Title string `json:"title"`
Status TaskStatus `json:"status" `
Created time.Time `json:"created"`
Modified time.Time `json:"modified" db:"modified"`
}

type Tasks []*Task
4 changes: 4 additions & 0 deletions chapter18/section72/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ require (
golang.org/x/sync v0.8.0
)

require filippo.io/edwards25519 v1.1.0 // indirect

require (
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sql-driver/mysql v1.8.1
github.com/jmoiron/sqlx v1.4.0
github.com/leodido/go-urn v1.4.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions chapter18/section72/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand All @@ -14,10 +16,16 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
Expand Down
70 changes: 70 additions & 0 deletions chapter18/section72/store/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package store

import (
"context"
"database/sql"
"fmt"
"time"

_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"github.com/myeunee/GolangStudy/chapter18/section72/clock"
"github.com/myeunee/GolangStudy/chapter18/section72/config"
)

func New(ctx context.Context, cfg *config.Config) (*sqlx.DB, func(), error) {
// sqlx.Connect를 사용하면 내부에서 ping함
db, err := sql.Open("mysql",
fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?parseTime=true",
cfg.DBUser, cfg.DBPassword,
cfg.DBHost, cfg.DBPort,
cfg.DBName,
),
)
if err != nil {
return nil, func() {}, err
}
// Open은 실제로 접속 테스트를 하지X
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
return nil, func() { _ = db.Close() }, err
}
xdb := sqlx.NewDb(db, "mysql")
return xdb, func() { _ = db.Close() }, nil
}

type Beginner interface {
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
}

type Preparer interface {
PreparexContext(ctx context.Context, query string) (*sqlx.Stmt, error)
}

type Execer interface {
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
NamedExecContext(ctx context.Context, query string, arg interface{}) (sql.Result, error)
}

type Queryer interface {
Preparer
QueryxContext(ctx context.Context, query string, args ...any) (*sqlx.Rows, error)
QueryRowxContext(ctx context.Context, query string, args ...any) *sqlx.Row
GetContext(ctx context.Context, dest interface{}, query string, args ...any) error
SelectContext(ctx context.Context, dest interface{}, query string, args ...any) error
}

var (
// 인터페이스가 기대한 대로 선언돼 있는지 확인
_ Beginner = (*sqlx.DB)(nil)
_ Preparer = (*sqlx.DB)(nil)
_ Queryer = (*sqlx.DB)(nil)
_ Execer = (*sqlx.DB)(nil)
_ Execer = (*sqlx.Tx)(nil)
)

type Repository struct {
Clocker clock.Clocker
}
44 changes: 44 additions & 0 deletions chapter18/section72/store/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package store

import (
"context"

"github.com/myeunee/GolangStudy/chapter18/section72/entity"
)

func (r *Repository) AddTask(
ctx context.Context, db Execer, t *entity.Task,
) error {
t.Created = r.Clocker.Now()
t.Modified = r.Clocker.Now()
sql := `INSERT INTO task
(title, status, created, modified)
VALUES (?, ?, ?, ?)`
result, err := db.ExecContext(
ctx, sql, t.Title, t.Status,
t.Created, t.Modified,
)
if err != nil {
return err
}
id, err := result.LastInsertId()
if err != nil {
return err
}
t.ID = entity.TaskID(id)
return nil
}

func (r *Repository) ListTasks(
ctx context.Context, db Queryer,
) (entity.Tasks, error) {
tasks := entity.Tasks{}
sql := `SELECT
id, title,
status, created, modified
FROM task;`
if err := db.SelectContext(ctx, &tasks, sql); err != nil {
return nil, err
}
return tasks, nil
}

0 comments on commit 19c1390

Please sign in to comment.