Last active
December 27, 2019 07:26
-
-
Save nomkhonwaan/c19e8ccf373bce1feb9ff9249b38c67d to your computer and use it in GitHub Desktop.
repository-pattern-ใน-go-5dfc2ab8ec12f08f3649c983
This file contains hidden or 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
package main | |
import ( | |
"context" | |
"database/sql" | |
"fmt" | |
_ "github.com/go-sql-driver/mysql" | |
"go.mongodb.org/mongo-driver/bson" | |
"go.mongodb.org/mongo-driver/mongo" | |
"go.mongodb.org/mongo-driver/mongo/options" | |
"strings" | |
"time" | |
) | |
// Post contains content of the blog platform | |
type Post struct { | |
ID int `bson:"id"` | |
Title string `bson:"title"` | |
Body string `bson:"body"` | |
CreatedAt *time.Time `bson:"createdAt"` | |
UpdatedAt *time.Time `bson:"updatedAt"` | |
} | |
// PostRepository is a contract for consuming data by business logic layer | |
type PostRepository interface { | |
// Return list of posts | |
FindAll() ([]Post, error) | |
// Return a single post by its ID | |
FindByID(id int) (Post, error) | |
} | |
// MariaDBPostRepository implements PostRepository for MariaDB | |
type MariaDBPostRepository struct { | |
*sql.DB | |
} | |
// FindAll returns list of posts | |
func (repo MariaDBPostRepository) FindAll() ([]Post, error) { | |
rows, err := repo.DB.Query(`SELECT id, title, body, created_at, updated_at FROM posts`) | |
if err != nil { | |
return nil, err | |
} | |
var posts []Post | |
for rows.Next() { | |
var p Post | |
err = rows.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt, &p.UpdatedAt) | |
if err != nil { | |
return nil, err | |
} | |
posts = append(posts, p) | |
} | |
return posts, nil | |
} | |
// FindByID returns a single post by its ID | |
func (repo MariaDBPostRepository) FindByID(id int) (Post, error) { | |
row := repo.DB.QueryRow(`SELECT id, title, body, created_at, updated_at FROM posts`) | |
var p Post | |
err := row.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt, &p.UpdatedAt) | |
return p, err | |
} | |
// MongoDBPostRepository implements PostRepository for MongoDB | |
type MongoDBPostRepository struct { | |
*mongo.Collection | |
} | |
// FindAll returns list of posts | |
func (repo MongoDBPostRepository) FindAll() ([]Post, error) { | |
cursor, err := repo.Collection.Find(context.Background(), bson.M{}) | |
if err != nil { | |
return nil, err | |
} | |
var posts []Post | |
for cursor.Next(context.Background()) { | |
var p Post | |
err = cursor.Decode(&p) | |
if err != nil { | |
return nil, err | |
} | |
posts = append(posts, p) | |
} | |
return posts, nil | |
} | |
// FindByID returns a single post by its ID | |
func (repo MongoDBPostRepository) FindByID(id int) (Post, error) { | |
result := repo.Collection.FindOne(context.Background(), bson.M{"id": id}) | |
var p Post | |
err := result.Decode(&p) | |
return p, err | |
} | |
func main() { | |
repo := newMariaDBRepository("<mariadb-user>", "<mariadb-password>", "<mariadb-host>", "<mariadb-database-name>") | |
// repo := newMongoDBRepository("mongodb://<mongodb-host>", "<mongodb-database-name>") | |
err := printAll(repo) | |
if err != nil { | |
panic(err) | |
} | |
} | |
func newMariaDBRepository(user, password, host, databaseName string) MariaDBPostRepository { | |
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true", user, password, host, databaseName)) | |
if err != nil { | |
panic(err) | |
} | |
return MariaDBPostRepository{db} | |
} | |
func newMongoDBRepository(uri, databaseName string) MongoDBPostRepository { | |
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri)) | |
if err != nil { | |
panic(err) | |
} | |
db := client.Database(databaseName) | |
return MongoDBPostRepository{db.Collection("posts")} | |
} | |
func printAll(repo PostRepository) error { | |
posts, err := repo.FindAll() | |
if err != nil { | |
return err | |
} | |
for _, p := range posts { | |
fmt.Printf("A %s was created at %s had %d words\n", p.Title, p.CreatedAt, count(p.Body)) | |
} | |
return nil | |
} | |
func count(s string) int { | |
return len(strings.Split(s, " ")) | |
} |
This file contains hidden or 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
package main | |
import "testing" | |
type mockPostRepository struct { | |
findAllCalls int | |
} | |
func (repo *mockPostRepository) FindAll() ([]Post, error) { | |
repo.findAllCalls++ | |
return []Post{ | |
{ | |
ID: 99, | |
Title: "test", | |
Body: "test", | |
}, | |
}, nil | |
} | |
func (repo *mockPostRepository) FindByID(id int) (Post, error) { | |
return Post{ | |
ID: 99, | |
Title: "test", | |
Body: "test", | |
}, nil | |
} | |
func TestPrintAll(t *testing.T) { | |
// Given | |
repo := &mockPostRepository{} | |
// When | |
printAll(repo) | |
// Then | |
if repo.findAllCalls != 1 { | |
t.Errorf("expect `findAll()` calls count 1 but got %d", repo.findAllCalls) | |
} | |
} |
This file contains hidden or 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
// MariaDBPostRepository implements PostRepository for MariaDB | |
type MariaDBPostRepository struct { | |
*sql.DB | |
} | |
// FindAll returns list of posts | |
func (repo MariaDBPostRepository) FindAll() ([]Post, error) { | |
rows, err := repo.DB.Query(`SELECT id, title, body, created_at, updated_at FROM posts`) | |
if err != nil { | |
return nil, err | |
} | |
var posts []Post | |
for rows.Next() { | |
var p Post | |
err = rows.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt, &p.UpdatedAt) | |
if err != nil { | |
return nil, err | |
} | |
posts = append(posts, p) | |
} | |
return posts, nil | |
} | |
// FindByID returns a single post by its ID | |
func (repo MariaDBPostRepository) FindByID(id int) (Post, error) { | |
row := repo.DB.QueryRow(`SELECT id, title, body, created_at, updated_at FROM posts`) | |
var p Post | |
err := row.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt, &p.UpdatedAt) | |
return p, err | |
} |
This file contains hidden or 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
// MongoDBPostRepository implements PostRepository for MongoDB | |
type MongoDBPostRepository struct { | |
*mongo.Collection | |
} | |
// FindAll returns list of posts | |
func (repo MongoDBPostRepository) FindAll() ([]Post, error) { | |
cursor, err := repo.Collection.Find(context.Background(), bson.M{}) | |
if err != nil { | |
return nil, err | |
} | |
var posts []Post | |
for cursor.Next(context.Background()) { | |
var p Post | |
err = cursor.Decode(&p) | |
if err != nil { | |
return nil, err | |
} | |
posts = append(posts, p) | |
} | |
return posts, nil | |
} | |
// FindByID returns a single post by its ID | |
func (repo MongoDBPostRepository) FindByID(id int) (Post, error) { | |
result := repo.Collection.FindOne(context.Background(), bson.M{"id": id}) | |
var p Post | |
err := result.Decode(&p) | |
return p, err | |
} |
This file contains hidden or 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
// Post contains content of the blog platform | |
type Post struct { | |
ID int `bson:"id"` | |
Title string `bson:"title"` | |
Body string `bson:"body"` | |
CreatedAt *time.Time `bson:"createdAt"` | |
UpdatedAt *time.Time `bson:"updatedAt"` | |
} |
This file contains hidden or 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
db.posts.drop(); | |
db.posts.insert({ id: 1, title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', body: 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto', createdAt: new Date() }); | |
db.posts.insert({ id: 2, title: 'qui est esse', body: 'est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla', createdAt: new Date() }); | |
db.posts.insert({ id: 3, title: 'ea molestias quasi exercitationem repellat qui ipsa sit aut', body: 'et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut', createdAt: new Date() }); | |
db.posts.insert({ id: 4, title: 'eum et est occaecati', body: 'ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit', createdAt: new Date() }); | |
db.posts.insert({ id: 5, title: 'nesciunt quas odio', body: 'repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque', createdAt: new Date() }); |
This file contains hidden or 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
DROP TABLE IF EXISTS posts; | |
CREATE TABLE posts ( | |
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, | |
title VARCHAR(255), | |
body TEXT, | |
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP | |
); | |
INSERT INTO posts (id, title, body) VALUES (1, 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'); | |
INSERT INTO posts (id, title, body) VALUES (2, 'qui est esse', 'est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla'); | |
INSERT INTO posts (id, title, body) VALUES (3, 'ea molestias quasi exercitationem repellat qui ipsa sit aut', 'et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut'); | |
INSERT INTO posts (id, title, body) VALUES (4, 'eum et est occaecati', 'ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit'); | |
INSERT INTO posts (id, title, body) VALUES (5, 'nesciunt quas odio', 'repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque'); |
This file contains hidden or 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
import "fmt" | |
import "strings" | |
// printAll will print all posts with its title, creation date-time and number of word in the body | |
func printAll(repo PostRepository) error { | |
posts, err := repo.FindAll() | |
if err != nil { | |
return err | |
} | |
for _, p := range posts { | |
fmt.Printf("A %s was created at %s had %d words\n", p.Title, p.CreatedAt, count(p.Body)) | |
} | |
return nil | |
} | |
func count(s string) int { | |
return len(strings.Split(s, " ")) | |
} |
This file contains hidden or 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
// PostRepository is a contract for consuming data by business logic layer | |
type PostRepository interface { | |
// Return list of posts | |
FindAll() ([]Post, error) | |
// Return a single post by its ID | |
FindByID(id int) (Post, error) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment