diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..7f011bc --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,40 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:58c033da727ebd5a6769209e479cac9a6e4dab53c879631af3d8161423099d57" + name = "github.com/go-chi/chi" + packages = [ + ".", + "middleware", + ] + pruneopts = "UT" + revision = "da24bba8dcd4021cafac38724bf10dccc97c3e36" + version = "v4.0.2" + +[[projects]] + digest = "1:ec6f9bf5e274c833c911923c9193867f3f18788c461f76f05f62bb1510e0ae65" + name = "github.com/go-sql-driver/mysql" + packages = ["."] + pruneopts = "UT" + revision = "72cd26f257d44c1114970e19afddcd812016007e" + version = "v1.4.1" + +[[projects]] + digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3" + name = "google.golang.org/appengine" + packages = ["cloudsql"] + pruneopts = "UT" + revision = "b2f4a3cf3c67576a2ee09e1fe62656a5086ce880" + version = "v1.6.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/go-chi/chi", + "github.com/go-chi/chi/middleware", + "github.com/go-sql-driver/mysql", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..1d36ab9 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,38 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/go-chi/chi" + version = "4.0.2" + +[[constraint]] + name = "github.com/go-sql-driver/mysql" + version = "1.4.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/helpers.go b/helpers.go new file mode 100644 index 0000000..a4f6248 --- /dev/null +++ b/helpers.go @@ -0,0 +1,34 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + "time" +) + +func catch(err error) { + if err != nil { + panic(err) + } +} + +func respondWithError(w http.ResponseWriter, code int, msg string) { + respondwithJSON(w, code, map[string]string{"message": msg}) +} + +func respondwithJSON(w http.ResponseWriter, code int, payload interface{}) { + response, _ := json.Marshal(payload) + fmt.Println(payload) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + w.Write(response) +} + +// Logger ... +func Logger() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println(time.Now(), r.Method, r.URL) + router.ServeHTTP(w, r) + }) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..d7fff8e --- /dev/null +++ b/main.go @@ -0,0 +1,146 @@ +package main + +import ( + "database/sql" + "encoding/json" + "fmt" + "net/http" + + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + _ "github.com/go-sql-driver/mysql" +) + +var router *chi.Mux +var db *sql.DB + +const ( + dbName = "go-mysql-crud" + dbPass = "" + dbHost = "localhost" + dbPort = "3306" +) + +func routers() *chi.Mux { + router.Get("/posts", AllPosts) + router.Get("/posts/{id}", DetailPost) + router.Post("/posts", CreatePost) + router.Put("/posts/{id}", UpdatePost) + router.Delete("/posts/{id}", DeletePost) + + return router +} + +func init() { + router = chi.NewRouter() + router.Use(middleware.Recoverer) + + dbSource := fmt.Sprintf("root:%s@tcp(%s:%s)/%s?charset=utf8", dbPass, dbHost, dbPort, dbName) + fmt.Println(dbSource) + var err error + db, err = sql.Open("mysql", dbSource) + + catch(err) +} + +// Post ... +type Post struct { + ID int `json:"id"` + Title string `json:"title"` + Content string `json:"content"` +} + +// CreatePost ... +func CreatePost(w http.ResponseWriter, r *http.Request) { + var post Post + json.NewDecoder(r.Body).Decode(&post) + + query, err := db.Prepare("Insert posts SET title=?, content=?") + catch(err) + + _, er := query.Exec(post.Title, post.Content) + catch(er) + defer query.Close() + + respondwithJSON(w, http.StatusCreated, map[string]string{"message": "successfully created"}) +} + +// UpdatePost ... +func UpdatePost(w http.ResponseWriter, r *http.Request) { + var post Post + id := chi.URLParam(r, "id") + json.NewDecoder(r.Body).Decode(&post) + + query, err := db.Prepare("Update posts set title=?, content=? where id=?") + catch(err) + _, er := query.Exec(post.Title, post.Content, id) + catch(er) + + defer query.Close() + + respondwithJSON(w, http.StatusOK, map[string]string{"message": "update successfully"}) +} + +// DeletePost ... +func DeletePost(w http.ResponseWriter, r *http.Request) { + id := chi.URLParam(r, "id") + + query, err := db.Prepare("delete from post where id=?") + catch(err) + _, er := query.Exec(id) + catch(er) + query.Close() + + respondwithJSON(w, http.StatusOK, map[string]string{"message": "deleted successfully"}) +} + +// AllPosts ... +func AllPosts(w http.ResponseWriter, r *http.Request) { + errors := []error{} + payload := []Post{} + + rows, err := db.Query("Select id, title, content From posts") + catch(err) + + defer rows.Close() + + for rows.Next() { + data := Post{} + + er := rows.Scan(&data.ID, &data.Title, &data.Content) + + if er != nil { + errors = append(errors, er) + } + payload = append(payload, data) + } + + respondwithJSON(w, http.StatusOK, payload) +} + +// DetailPost ... +func DetailPost(w http.ResponseWriter, r *http.Request) { + payload := Post{} + id := chi.URLParam(r, "id") + + row := db.QueryRow("Select if, title, content From posts where id=?", id) + + err := row.Scan( + &payload.ID, + &payload.Title, + &payload.Content, + ) + + if err != nil { + respondWithError(w, http.StatusNotFound, "no rows in result set") + return + } + + respondwithJSON(w, http.StatusOK, payload) +} + +// +func main() { + routers() + http.ListenAndServe(":8005", Logger()) +}