이 글은 골든래빗 《Tucker 의 Go 언어프로그래밍》의 3단계 써머리입니다.
Todo 리스트 웹사이트
구현 순서
- 서비스 정의
- Todo 구조체 생성
- RESTful API에 맞춰서 핸들러 생성
- 화면 구성 (프론트)
- 웹 브라우저 동작 확인
패키지 사용
`$ go get github.com/urfave/negroni`
- 로그 / panic 복구 / 파일서버 기능 지원
`$ go get github.com/unrolled/render`
- 웹 서버 응답을 구현하는데 유용한 패키지
구조체 정의
type Todo struct {
ID int `json:"id,omitempty"`
Name string `json:"name"`
Completed bool `json:"completed,omitempty"`
}
RESTful API 정의
[GET] /todos -> 전체 할일 목록 반환
[POST] /todos -> 새로운 할 일 등록
[PUT] /todos/id -> id에 해당하는 할 일 업데이트
[DELETE] /todos/id -> id에 해당하는 할 일 삭제
Backend
package main
import (
"encoding/json"
"log"
"net/http"
"sort"
"strconv"
"github.com/unrolled/render"
"github.com/urfave/negroni"
)
var rd *render.Render
type Todo struct {
ID int `json:"id,omitempty"`
Name string `json:"name"`
Completed bool `json:"completed,omitempty"`
}
var todoMap map[int]Todo
var lastID int = 0
func MakeWebHandler() http.Handler {
todoMap = make(map[int]Todo)
mux := mux.NewRouter()
mux.HandleFunc("/", http.FileServer(http.Dir("public")))
mux.HandleFunc("/todos", GetTodoListHandler).Method("GET")
mux.HandleFunc("/todos", PostTodoHandler).Method("POST")
mux.HandleFunc("/todos/{id:[0-9]+}", RemoveTodoHandler).Method("DELETE")
mux.HandleFunc("/todos/{id:[0-9]+}", UpdateTodoHandler).Method("PUT")
return mux
}
type Todos []Todo
func (t Todos) Len() int {
return len(t)
}
func (t Todos) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
func (t Todos) Less(i, j int) bool {
return t[i].ID > t[j].ID
}
func GetTodoListHandler(w http.ResponseWriter, r *http.Request) {
list := make(Todos, 0)
for _, todo := range todoMap {
list = append(list, todo)
}
sort.Sort(list)
rd.JSON(w, http.StatusOK, list)
}
func PostTodoHandler(w http.ResponseWriter, r *http.Request) {
var todo Todo
err := json.NewDecoder(r.Body).Decode(&todo)
if err != nil {
log.Fatal(err)
w.WriteHeader(http.StatusBadRequest)
return
}
lastID++
todo.ID = lastID
todoMap[lastID] = todo
rd.JSON(w, http.StatusCreated, todo)
}
type Success struct {
Success bool `json:"success"`
}
func RemoveTodoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
if _, ok := todoMap[id]; ok {
delete(todoMap, id)
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusNotFound, Success{false})
}
}
func UpdateTodoHandler(w http.ResponseWriter, r *http.Request) {
var newTodo Todo
err := json.NewDecoder(r.Body).Decode(&newTodo)
if err != nil {
log.Fatal(err)
w.WriteHeader(http.StatusBadRequest)
return
}
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
if todo, ok := todoMap[id]; ok {
todo.Name = newTodo.Name
todo.Completed = newTodo.Completed
rd.JSON(w, http.StatusOK, Success{true})
} else {
rd.JSON(w, http.StatusBadRequest, Success{false})
}
}
func main() {
rd = render.New()
m := MakeWebHandler()
n := negroni.Classic()
n.UseHandler(m)
log.Println("Started App")
err := http.ListenAndServe(":3000", n)
if err != nil {
panic(err)
}
}
[3계층] 프론트엔드, 백엔드, 데이터 베이스
'STUDY > Go Lang' 카테고리의 다른 글
[Go / 백준 2588번] 곱셈 (1) | 2024.09.10 |
---|---|
[Go / 백준 18108번] 1998년생인 내가 태국에서는 2541년생?! (0) | 2024.09.09 |
[3단계] Go 프로그래밍에 유용한 기법 익히기 (1) (0) | 2023.11.05 |
[Go Lang] 고급 기법으로 Go 레벨업하기 (2) (0) | 2023.10.29 |
[GoLang] 고급 기법으로 Go 레벨업하기 (1) (1) | 2023.10.22 |