먼저 심플한 코드 부터 작성 해봅시다!main.go
package main
type User struct {
Name string `json:"name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
func getUserInfoHandler(w http.ResponseWriter, r *http.Request) {
user := User{Name: "turcker", Email: "turcker@naver.com"}
w.Header().Add("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
data, _ := json.Marshal(user)
fmt.Fprint(wm string(data))
}
func addUserHandler(w http.ResponseWriter, r *http.Request) {
user := new(User)
err := json.NewDecoder(r.Body).Decode(user)
if err != nil {
rd.Text(w, http.StatusBadRequest, err.Error())
return
}
user.CreatedAt = time.Now()
w.Header().Add("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
data, _ := json.Marshal(user)
fmt.Fprint(wm string(data)
}
func helloHandler(w http.ResponseWriter, r *http.Request) { // 2
tmpl, err := template.new("Hello").ParseFiles("templates/hello.tmpl")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, err)
return
}
tmpl.ExecuteTemplate(w, "hello.tmpl", "changbeom")
}
func main() {
mux := pat.New()
mux.Get("/users", getUserInfoHandler) // 1
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
http.ListenAndServe(":3000", mux)
이번에는 gorilla mux가 아닌 gorilla pat을 사용할 것인데요, 좀 더 심플한 라우터라고 생각하면 됩니다.
링크를 들어가면 자세한 내용을 볼 수 있으며
go get github.com/gorilla/pat
를 사용하여 다운을 받아 봅시다!
1 : 기존 gorilla mux를 사용하여 GET, POST를 했을 때 쓰는 방식이 조금 다른 것을 확인 할 수 있습니다.
2 : 지난번에 했던 템플릿을 사용해보려 합니다.
코드 구조들은 지난번에 했었던 RESTful API와 비슷한 것을 확인 할 수 있습니다.
이어서 templates/hello.tmpl
를 추가하여 코드를 작성 합니다.
<html>
<head>
<title>Hello Go in Web</title>
</head>
<body>
Hello World{{.}}
</body>
</html>
이제 동작을 확인해보기 위해 클라이언트 앱으로 동작시켜 봅시다!
GET
POST
Hello
이렇게 결과를 확인 할 수 있습니다.
이제 매번 JSON을 쓰고, 템플릿을 전하는게 귀찮기 때문에 간단하게 해주는 패키지를 추가할 것인데요,
unrolled -render 라는 패키지 입니다. 해당 링크에 들어가면 자세한 내용이 나오며,
설치는
github.com/unrolled/render
으로 해주면 됩니다.
사용법은 간단합니다. 먼저 전역변수인 rd를 추가해줍니다.
var rd *render.Render
이렇게 하면 render의 패키지가 import하게 됩니다.
그 다음 main.go
에서 인스턴스를 만든뒤 코드를 수정해 줍니다.
func getUserInfoHandler(w http.ResponseWriter, r *http.Request) {
user := User{Name: "tucker", Email: "tucker@naver.com"}
rd.JSON(w, http.StatusOK, user) // 1
}
func addUserHandler(w http.ResponseWriter, r *http.Request) {
user := new(User)
err := json.NewDecoder(r.Body).Decode(user)
if err != nil {
rd.Text(w, http.StatusBadRequest, err.Error())
return
}
user.CreatedAt = time.Now()
rd.JSON(w, http.StatusOK, user)
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
rd.HTML(w, http.StatusOK, "hello", "Tucker") // 2
}
func main() {
rd = render.New() // 2
mux := pat.New()
mux.Get("/users", getUserInfoHandler)
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
http.ListenAndServe(":3000", n)
}
1 : 첫번째 인자가 ResponseWriter, 두번째 인자가 status, 세번째 인자가 JSON으로 바꾸고싶은 인스턴스입니다.
이 한줄로 끝이 납니다.
2 : 첫번째 인자가 ResponseWriter, 두번째 인자가 status, 세번째 인자가 템플릿 파일, 네번째 인자가 템플릿에 넣을 인스턴스 값입니다.
이제 실행을 시켜봅시다!
GET
POST
HELLO
그리고 Hello 템플릿에서 .tmpl외에도 .HTML이 될 수 있는데요
이 때 템플릿을 .HTML로 변경하면 클라이언트 앱에서 읽어오지 못합니다.
그래서 HTML도 읽어 줄 수 있게 하기 위해 Main 부분을 수정해줍니다.
func main() {
rd = render.New(render.Options{
Directory: "template",
Extensions: []string{".html", ".tmpl"},
})
mux := pat.New()
mux.Get("/users", getUserInfoHandler)
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
http.ListenAndServe(":3000", n)
}
Extensions이라는 옵션이 있는데 템플릿을 읽어올 때 어떤 확장자를 읽을지 알려주는 옵션입니다.
마찬가지로 디렉토리가 바뀔 수 있는데, 어떤 디렉토리를 읽고자 하는지 사용하는 옵션입니다.
이번에는 템플릿에 어떤 레이아웃을 추가하는 것을 해보고자 합니다.
저번 시간에 템플릿을 기능에 따라 2개 나누었듯이 나눠봅시다!
template/body.html
Name: {{.Name}}
Email : {{.Email}}
그리고 template/hello.HTML
를 body를 넣을 부분을 수정해주자!
<html>
<head>
<title>Hello Go in Web</title>
</head>
<body>
Hello World
{{ yield }}
</body>
</html>
그리고 다시 돌아와 Main 부분을 수정해줍니다.
func helloHandler(w http.ResponseWriter, r *http.Request) {
user := User{Name: "tucker", Email: "tucker@naver.com"} // 1
rd.HTML(w, http.StatusOK, "body", user)
}
func main() {
rd = render.New(render.Options{
Directory: "template",
Extensions: []string{".html", ".tmpl"},
Layout: "hello",
})
mux := pat.New()
mux.Get("/users", getUserInfoHandler)
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
http.ListenAndServe(":3000", n)
}
1 : body 템플릿에 넣어주기 위해 수정했습니다.
이 상태에서 실행하게 되면
정상적으로 작동 되는 것을 확인 할 수 있습니다.
body는 {{ yield }}로 템플릿을 지정했지만 title부분도 템플릿으로 지정해주고 싶다면 이렇게 수정해주면 됩니다.
<html>
<head>
<title>{{ partial "title" }}</title>
</head>
<body>
Hello World
{{ yield }}
</body>
</html>
이렇게 만들어 준 뒤 title에 해당하는 템플릿을 만들면 됩니다! template/title-body.html
Partial Go in Web
title-body라고 이름을 만들면 layout에서 해당 title에 해당하는 이름과 main.go의 body값을 읽은 부분을 채워주게 됩니다.
마지막으로 설치해볼 패키지는 negroni라는 패키지인데 HTTP 미들웨어 입니다.
기본적으로 많이 쓰이는 부가기능들을 제공하는 패키지 라고 생각하면 됩니다.
링크에 들어가면 자세한 내용을 알 수 있는데 기본적으로 제공하는 것이 Recovery, Logger, Static 입니다.
이것 또한 설치 해줍니다.
go get github.com/urfave/negroni
main.go를 수정하기 앞서 public 폴더에 index.html을 생성합니다.
<html>
<head>
<title>Go in Web 11</title>
</head>
<body>
<h1>Hello Go in Web</h1>
</body>
</html>
기본적인 것을 사용할 때는 간단한데
func main() {
rd = render.New(render.Options{
Directory: "template",
Extensions: []string{".html", ".tmpl"},
Layout: "hello",
})
mux := pat.New()
mux.Get("/users", getUserInfoHandler)
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
n := negroni.Classic() // 1
n.UseHandler(mux) // 2
http.ListenAndServe(":3000", n) // 3
}
1 : 이걸 사용하면 핸들러가 하나 나옵니다.
2 : mux를 매핑해서 부가기능들을 추가해줍니다.
3 : 핸들러의 n을 추가해줍니다.
그러면 n이 가지고 있는것이 기본 파일 서버를 가지고 있고, log를 찍는 기능을 제공하고 있습니다.
실행해보면
정상적으로 화면이 나오고,
터미널창에 log가 찍힌 것을 확인 할 수 있습니다.
풀소스
main.go
package main
import (
"encoding/json"
"net/http"
"time"
"github.com/gorilla/pat"
"github.com/unrolled/render"
"github.com/urfave/negroni"
)
var rd *render.Render
type User struct {
Name string `json:"name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
func getUserInfoHandler(w http.ResponseWriter, r *http.Request) {
user := User{Name: "tucker", Email: "tucker@naver.com"}
rd.JSON(w, http.StatusOK, user)
}
func addUserHandler(w http.ResponseWriter, r *http.Request) {
user := new(User)
err := json.NewDecoder(r.Body).Decode(user)
if err != nil {
rd.Text(w, http.StatusBadRequest, err.Error())
return
}
user.CreatedAt = time.Now()
rd.JSON(w, http.StatusOK, user)
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
user := User{Name: "tucker", Email: "tucker@naver.com"}
rd.HTML(w, http.StatusOK, "body", user)
}
func main() {
rd = render.New(render.Options{
Directory: "template",
Extensions: []string{".html", ".tmpl"},
Layout: "hello",
})
mux := pat.New()
mux.Get("/users", getUserInfoHandler)
mux.Post("/users", addUserHandler)
mux.Get("/hello", helloHandler)
n := negroni.Classic()
n.UseHandler(mux)
http.ListenAndServe(":3000", n)
}
template/body.html
Name: {{.Name}}
Email: {{.Email}}
template/hello.html
<html>
<head>
<title>{{ partial "title" }}</title>
</head>
<body>
Hello World
{{ yield }}
</body>
</html>
template/title-body.html
Partial Go in Web
public/index.html
<html>
<head>
<title>Go in Web 11</title>
</head>
<body>
<h1>Hello Go in Web</h1>
</body>
</html>
'프로그래밍(Web) > Golang' 카테고리의 다른 글
[바미] Go - Template (0) | 2020.12.17 |
---|---|
[바미] Go - SQL query(CRUD) (0) | 2020.12.17 |
[바미] Go - Decorator 패턴 (0) | 2020.12.17 |
[바미] Go - RESTful API(PUT, GET list) (0) | 2020.12.17 |
[바미] Go - RESTful API(DELETE) (0) | 2020.12.17 |