-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
400 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export DB_HOST="127.0.0.1" | ||
export DB_PORT="3306" | ||
export DB_USER="devuser" | ||
export DB_PASSWORD="Passw0rd!" | ||
export DB_NAME="hexample" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package controller | ||
|
||
import ( | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/rema424/hexample/internal/service2" | ||
) | ||
|
||
// Controller2 ... | ||
type Controller2 struct { | ||
p *service2.Provider | ||
} | ||
|
||
// NewController2 ... | ||
func NewController2(p *service2.Provider) *Controller2 { | ||
return &Controller2{p} | ||
} | ||
|
||
// HandlePersonRegister ... | ||
// curl -X POST -H 'Content-type: application/json' -d '{"name": "Alice", "email": "[email protected]"}' localhost:8080/people | ||
func (ctrl *Controller2) HandlePersonRegister(c echo.Context) error { | ||
in := struct { | ||
Name string `json:"name"` | ||
Email string `json:"email"` | ||
}{} | ||
|
||
if err := c.Bind(&in); err != nil { | ||
return c.JSON(http.StatusBadRequest, err.Error()) | ||
} | ||
|
||
// TODO: implement | ||
// if err := c.Validate(&in); err != nil { | ||
// return c.JSON(http.StatusUnprocessableEntity, err.Error()) | ||
// } | ||
|
||
ctx := c.Request().Context() | ||
psn, err := ctrl.p.RegisterPerson(ctx, in.Name, in.Email) | ||
if err != nil { | ||
return c.JSON(http.StatusInternalServerError, err.Error()) | ||
} | ||
|
||
return c.JSON(http.StatusOK, psn) | ||
} | ||
|
||
// HandlePersonGet ... | ||
// curl localhost:8080/people/999 | ||
func (ctrl *Controller2) HandlePersonGet(c echo.Context) error { | ||
id, err := strconv.Atoi(c.Param("personID")) | ||
if err != nil { | ||
return c.JSON(http.StatusUnprocessableEntity, err.Error()) | ||
} | ||
|
||
ctx := c.Request().Context() | ||
psn, err := ctrl.p.GetPersonByID(ctx, int64(id)) | ||
if err != nil { | ||
return c.JSON(http.StatusInternalServerError, err.Error()) | ||
} | ||
|
||
return c.JSON(http.StatusOK, psn) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package service2 | ||
|
||
// Person ... | ||
type Person struct { | ||
ID int64 `db:"kokoha"` | ||
Name string `db:"tekitode"` // sql.NullString はインフラに結合するので使わない | ||
Email string `db:"yoiyo"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package service2 | ||
|
||
import "context" | ||
|
||
// Provider ... | ||
type Provider struct { | ||
r Repository | ||
} | ||
|
||
// NewProvider ... | ||
func NewProvider(r Repository) *Provider { | ||
return &Provider{r} | ||
} | ||
|
||
// RegisterPerson ... | ||
func (p *Provider) RegisterPerson(ctx context.Context, name, email string) (Person, error) { | ||
psn := Person{ | ||
Name: name, | ||
Email: email, | ||
} | ||
|
||
psn, err := p.r.RegisterPerson(ctx, psn) | ||
if err != nil { | ||
return Person{}, err | ||
} | ||
|
||
return psn, nil | ||
} | ||
|
||
// GetPersonByID ... | ||
func (p *Provider) GetPersonByID(ctx context.Context, id int64) (Person, error) { | ||
psn, err := p.r.GetPersonByID(ctx, id) | ||
if err != nil { | ||
return Person{}, err | ||
} | ||
|
||
return psn, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package service2 | ||
|
||
import "context" | ||
|
||
// Repository ... | ||
type Repository interface { | ||
RegisterPerson(context.Context, Person) (Person, error) | ||
GetPersonByID(context.Context, int64) (Person, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package service2 | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/jmoiron/sqlx" | ||
) | ||
|
||
// RepositoryImpl ... | ||
type RepositoryImpl struct { | ||
db *sqlx.DB | ||
} | ||
|
||
// NewRepositoryImpl ... | ||
func NewRepositoryImpl(db *sqlx.DB) *RepositoryImpl { | ||
return &RepositoryImpl{db} | ||
} | ||
|
||
// RegisterPerson ... | ||
func (r *RepositoryImpl) RegisterPerson(ctx context.Context, p Person) (Person, error) { | ||
q := `INSERT INTO person (name, email) VALUES (:tekitode, :yoiyo);` | ||
res, err := r.db.NamedExecContext(ctx, q, p) | ||
if err != nil { | ||
return Person{}, err | ||
} | ||
|
||
id, err := res.LastInsertId() | ||
if err != nil { | ||
return Person{}, err | ||
} | ||
|
||
p.ID = id | ||
return p, nil | ||
} | ||
|
||
// GetPersonByID ... | ||
func (r *RepositoryImpl) GetPersonByID(ctx context.Context, id int64) (Person, error) { | ||
// DB上のnull対策はここで実装する | ||
q := ` | ||
SELECT | ||
COALESCE(id, 0) AS 'kokoha', | ||
COALESCE(name, '') AS 'tekitode', | ||
COALESCE(email, '') AS 'yoiyo' | ||
FROM person | ||
WHERE id = ?; | ||
` | ||
var p Person | ||
err := r.db.GetContext(ctx, &p, q, id) | ||
return p, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package service2 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math/rand" | ||
"sync" | ||
"time" | ||
) | ||
|
||
var src = rand.NewSource(time.Now().UnixNano()) | ||
|
||
// RepositoryImplMock ... | ||
type RepositoryImplMock struct { | ||
db *MockDB | ||
} | ||
|
||
// MockDB ... | ||
type MockDB struct { | ||
mu sync.RWMutex | ||
data map[int64]Person | ||
} | ||
|
||
// NewMockDB ...s | ||
func NewMockDB() *MockDB { | ||
return &MockDB{data: make(map[int64]Person)} | ||
} | ||
|
||
// NewRepositoryImplMock ... | ||
func NewRepositoryImplMock(db *MockDB) *RepositoryImplMock { | ||
return &RepositoryImplMock{db} | ||
} | ||
|
||
// RegisterPerson ... | ||
func (r *RepositoryImplMock) RegisterPerson(ctx context.Context, p Person) (Person, error) { | ||
r.db.mu.Lock() | ||
defer r.db.mu.Unlock() | ||
|
||
// 割り当て可能なIDを探す | ||
var id int64 | ||
for { | ||
id = src.Int63() | ||
_, ok := r.db.data[id] | ||
if !ok { | ||
break | ||
} | ||
} | ||
|
||
p.ID = id | ||
r.db.data[p.ID] = p | ||
|
||
return p, nil | ||
} | ||
|
||
// GetPersonByID ... | ||
func (r *RepositoryImplMock) GetPersonByID(ctx context.Context, id int64) (Person, error) { | ||
r.db.mu.RLock() | ||
defer r.db.mu.RUnlock() | ||
|
||
if p, ok := r.db.data[id]; ok { | ||
return p, nil | ||
} | ||
return Person{}, fmt.Errorf("person not found - id: %d", id) | ||
} |
Oops, something went wrong.