리팩토링이란?
Go web 10에서 만든 app.go는 메모리맵을 가지며 컨트롤 하고 있어서 의존성이 매우 높았기 때문에, 의존성을 끊어내기 위해 분리 시킴
이렇게 함으로써 메모리에 해당하는 부분은 model패키지에서 컨트롤 하게 된다.
ex) app.go
package app
import (
"net/http"
"strconv"
"web10/model"
"github.com/gorilla/mux"
"github.com/unrolled/render"
)
var rd *render.Render
func indexHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/todo.html", http.StatusTemporaryRedirect)
}
// 리스트를 받아서 제이슨형태로 넘겨줌
func getTodoListHandler(w http.ResponseWriter, r *http.Request) {
// list := []*model.Todo{}
// for _, v := range todoMap {
// // map의 인덱스 만큼 반복
// // 키는 받지않고 value만 받음
// list = append(list, v)
// // list에 v값을 어팬드
// }
list := model.GetTodos() // model 패키지에서 불러옴
rd.JSON(w, http.StatusOK, list)
// json형태로 반환
}
func addTodoHandler(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("name") // 리퀘스트의 키로 name을 읽음
todo := model.AddTodo(name)
// id := len(todoMap) + 1 // map의 갯수만큼 id
// todo := &Todo{id, name, false, time.Now()} // 포인터형 구조체 Todo를 생성
// todoMap[id] = todo // todo의 데이터를 맵에 넣음
rd.JSON(w, http.StatusCreated, todo) // json형태로 반환
}
type Success struct {
Success bool `json:"success"`
}
func removeTodoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
ok := model.RemoveTodo(id)
if ok {
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusOK, Success{false})
}
// if _, ok := todoMap[id]; ok {
// delete(todoMap, id)
// rd.JSON(w, http.StatusOK, Success{true})
// } else {
// rd.JSON(w, http.StatusOK, Success{false})
// }
}
func completeTodoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
complete := r.FormValue("complete") == "true"
ok := model.CompleteTodo(id, complete)
if ok {
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusOK, Success{false})
}
// value 값에서 complete의 값을 받음
// if todo, ok := todoMap[id]; ok { // 맵에 있는지 확인
// todo.Completed = complete // 맵에 있는경우 변경
// rd.JSON(w, http.StatusOK, Success{true}) //제이슨 값으로 변환후 true 반환
// } else {
// rd.JSON(w, http.StatusOK, Success{false})
// } // 맵에 없을 경우 false 반환
}
// func addTestTodos() {
// todoMap[1] = &Todo{1, "Buy a milk", false, time.Now()}
// todoMap[2] = &Todo{2, "Exercise", true, time.Now()}
// todoMap[3] = &Todo{3, "Home Work", false, time.Now()}
// }
func MakeHandler() http.Handler {
// todoMap = make(map[int]*Todo)
rd = render.New()
r := mux.NewRouter()
r.HandleFunc("/todos", getTodoListHandler).Methods("GET")
r.HandleFunc("/todos", addTodoHandler).Methods("POST")
r.HandleFunc("/todos/{id:[0-9]+}", removeTodoHandler).Methods("DELETE")
r.HandleFunc("complete-todo/{id:[0-9]+", completeTodoHandler)
r.HandleFunc("/", indexHandler)
return r
}
ex) model.go
package model
import "time"
type Todo struct {
ID int `json:"id"`
Name string `json:"name"`
Completed bool `json:"completed"`
CreatedAt time.Time `json:"created_at"`
}
// Todo의 데이터를 가지고 있는 인메모리 스트럭처
var todoMap map[int]*Todo
func GetTodos() []*Todo {
return nil
}
func AddTodo(name string) *Todo {
return nil
}
func RemoveTodo(id int) bool {
return nil
}
func CompleteTodo(id int, complete bool) bool {
return false
}
ex) app.go
package app
import (
"net/http"
"strconv"
"web10/model"
"github.com/gorilla/mux"
"github.com/unrolled/render"
)
var rd *render.Render
func indexHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/todo.html", http.StatusTemporaryRedirect)
}
// 리스트를 받아서 제이슨형태로 넘겨줌
func getTodoListHandler(w http.ResponseWriter, r *http.Request) {
list := model.GetTodos() // model 패키지에서 불러옴
rd.JSON(w, http.StatusOK, list)
// json형태로 반환
}
func addTodoHandler(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("name") // 리퀘스트의 키로 name을 읽음
todo := model.AddTodo(name)
rd.JSON(w, http.StatusCreated, todo) // json형태로 반환
}
type Success struct {
Success bool `json:"success"`
}
func removeTodoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
ok := model.RemoveTodo(id)
if ok {
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusOK, Success{false})
}
}
func completeTodoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
complete := r.FormValue("complete") == "true"
ok := model.CompleteTodo(id, complete)
if ok {
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusOK, Success{false})
}
}
func MakeHandler() http.Handler {
rd = render.New()
r := mux.NewRouter()
r.HandleFunc("/todos", getTodoListHandler).Methods("GET")
r.HandleFunc("/todos", addTodoHandler).Methods("POST")
r.HandleFunc("/todos/{id:[0-9]+}", removeTodoHandler).Methods("DELETE")
r.HandleFunc("complete-todo/{id:[0-9]+", completeTodoHandler)
r.HandleFunc("/", indexHandler)
return r
}
ex) model.go
package model
import (
"time"
)
type Todo struct {
ID int `json:"id"`
Name string `json:"name"`
Completed bool `json:"completed"`
CreatedAt time.Time `json:"created_at"`
}
// Todo의 데이터를 가지고 있는 인메모리 스트럭처
var todoMap map[int]*Todo
// todoMap 초기화
func init() {
todoMap = make(map[int]*Todo)
}
func GetTodos() []*Todo {
list := []*Todo{}
for _, v := range todoMap {
// map의 인덱스 만큼 반복
// 키는 받지않고 value만 받음
list = append(list, v)
// list에 v값을 어팬드
}
return list
}
func AddTodo(name string) *Todo {
id := len(todoMap) + 1 // map의 갯수만큼 id
todo := &Todo{id, name, false, time.Now()} // 포인터형 구조체 Todo를 생성
todoMap[id] = todo // todo의 데이터를 맵에 넣음
return todo
}
func RemoveTodo(id int) bool {
if _, ok := todoMap[id]; ok {
delete(todoMap, id)
return true
}
return false
}
func CompleteTodo(id int, complete bool) bool {
if todo, ok := todoMap[id]; ok { // 맵에 있는지 확인
todo.Completed = complete // 맵에 있는경우 변경
return true
}
return false
}