Skip to content

Commit

Permalink
[update] 1.0.0 - MVC
Browse files Browse the repository at this point in the history
  • Loading branch information
bmf-san committed Jun 2, 2019
1 parent 83364d4 commit 2806997
Show file tree
Hide file tree
Showing 17 changed files with 280 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/app/.env
launch.json
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
# go-crud-boilerplate
This is a boilerplate for creating CRUD application working with go.
# go-api-boilerplate
This is an api boilerplate built with golang.

- golang
- mysql
- docker

# Get Started
`cp app/.env_example app/.env`
`docker-compose build`
`docker-compose up`

After running docker, you need to execute sql files in `app/database/sql`.

# References
I refered to this repository.

- [github - rymccue/golang-standard-lib-rest-api](https://github.com/rymccue/golang-standard-lib-rest-api)
7 changes: 7 additions & 0 deletions app/.env_example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SERVER_PORT=8080
DB_DRIVER=mysql
DB_USER=root
DB_PASSWORD=password
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=go_api_boilerplate
19 changes: 19 additions & 0 deletions app/.realize.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
settings:
legacy:
force: false
interval: 0s
schema:
- name: go-api-boilerplate
path: .
commands:
run:
status: true
watcher:
extensions:
- go
paths:
- /
ignored_paths:
- .git
- .realize
- vendor
32 changes: 32 additions & 0 deletions app/config/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package config

import (
"bufio"
"fmt"
"os"
"strings"
)

func LoadEnv() {
filePath := ".env"
f, err := os.Open(filePath)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", filePath, err)
os.Exit(1)
}
defer f.Close()

lines := make([]string, 0, 100)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", filePath, err)
}

for _, e := range lines {
pair := strings.Split(e, "=")
os.Setenv(pair[0], pair[1])
}
}
23 changes: 23 additions & 0 deletions app/database/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package database

import (
"database/sql"
"fmt"
"log"
"os"
)

func Connect() (db *sql.DB) {
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_DATABASE"))
db, err := sql.Open(os.Getenv("DB_DRIVER"), dataSourceName)
if err != nil {
log.Fatal(err)
}

err = db.Ping()
if err != nil {
fmt.Println("Failed to connected DB:", err)
}

return db
}
5 changes: 5 additions & 0 deletions app/database/sql/faker.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
INSERT INTO users(name) VALUES('foo');
INSERT INTO users(name) VALUES('bar');

INSERT INTO posts(user_id, body) VALUES(1, 'Hello World');
INSERT INTO posts(user_id, body) VALUES(2, 'Hi');
10 changes: 10 additions & 0 deletions app/database/sql/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS `users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `posts` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` INT UNSIGNED NOT NULL,
`body` TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
54 changes: 54 additions & 0 deletions app/handler/user_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package handler

import (
"database/sql"
"encoding/json"
"log"
"net/http"

"../repository"
)

type UserHandler struct {
DB *sql.DB
}

func NewUserHandler(db *sql.DB) *UserHandler {
return &UserHandler{
DB: db,
}
}

func (uh *UserHandler) Index(w http.ResponseWriter, r *http.Request) {
// TODO: 以下のメソッド方針で実装
// list 一覧を取得する
// get IDを指定して、一件取得する
// insert 新規作成する
// update 上書きする
// patch 部分的に上書きする
// delete 指定したIDに対応するものを削除する

// TODO: method 振り分け
// switch r.Method {
// case http.MethodPost:
// Register(w, r)
// case http.MethodGet:
// Reader(w, r)
// case http.MethodPut:
// Updater(w, r)
// case http.MethodDelete:
// Deleter(w, r)
// default:
// NotFoundResources(w, r)

// TODO: ルーティング処理は切り出したい controllerとhandlerは別・・? handlerにできるならhandlerにリネームした
// TODO: ここが処理のメイン userrepositoryはどっかの引数に取るとかしても良いのでは
users, err := repository.UserRepositoryIndex(uh.DB)
if err != nil {
log.Fatalf("show users list error: %s", err)
http.Error(w, "", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
24 changes: 24 additions & 0 deletions app/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"log"
"net/http"
"os"

"./config"
"./database"
"./route"
_ "github.com/go-sql-driver/mysql"
)

func main() {
config.LoadEnv()
db := database.Connect()

mux := http.NewServeMux()
route.Dispatch(mux, db)

if err := http.ListenAndServe(":"+os.Getenv("SERVER_PORT"), mux); err != nil {
log.Fatal(err)
}
}
6 changes: 6 additions & 0 deletions app/model/user_model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package model

type UserModel struct {
ID int `json:"id"`
Name string `json:"name"`
}
20 changes: 20 additions & 0 deletions app/repository/user_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package repository

import (
"database/sql"

"../model"
)

func UserRepositoryIndex(db *sql.DB) (*model.UserModel, error) {
const query = `
select
id,
name
from
users
`
var user model.UserModel
err := db.QueryRow(query).Scan(&user.ID, &user.Name)
return &user, err
}
14 changes: 14 additions & 0 deletions app/route/routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package route

import (
"database/sql"
"net/http"

"../handler"
)

func Dispatch(mux *http.ServeMux, db *sql.DB) {
userHandler := handler.NewUserHandler(db)

mux.HandleFunc("/users", userHandler.Index)
}
24 changes: 24 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: "3"
services:
golang:
container_name: "golang"
build: ./docker/go
volumes:
- ./app:/usr/local/project:delegated
ports:
- "8080:8080"
depends_on:
- mysql
mysql:
container_name: "mysql"
build: ./docker/mysql
ports:
- "3306:3306"
volumes:
- mysql_db:/var/lib/mysql:delegated
environment:
- MYSQL_DATABASE=go_api_boilerplate
- MYSQL_ROOT_PASSWORD=password
volumes:
mysql_db:
driver: local
9 changes: 9 additions & 0 deletions docker/go/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM golang:1.10.7-alpine3.8

WORKDIR /usr/local/project

RUN apk add --no-cache git
RUN go get github.com/go-sql-driver/mysql
RUN go get github.com/oxequa/realize

CMD realize start
5 changes: 5 additions & 0 deletions docker/mysql/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM mysql:5.7

ADD ./my.cnf /etc/mysql/conf.d/my.cnf

CMD ["mysqld"]
8 changes: 8 additions & 0 deletions docker/mysql/my.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8

0 comments on commit 2806997

Please sign in to comment.