///
Search

11_Go Web Render, Pat, Negroni

/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: "yklovejesus", Email: "yklovejesus@gmail.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)
Go
복사
이번에는 gorilla mux가 아닌 gorilla pat을 사용할 예정
좀 더 심플한 라우터라고 생각하면 된다.
설치 명령어
go get github.com/gorilla/pat
Go
복사
기존 gorilla mux를 사용하여 GET,POST를 했을 때 쓰는 방식이 조금 다른 것을 확인 할 수 있다.
지난번에 했던 템플릿을 사용해보려 한다.
코드 구조들은 지난번에 했었던 RESTful API와 비슷한 것을 확인 할 수 있다.

/templates/hello.html

<html> <head> <title>Hello Go in Web</title> </head> <body> Hello World{{.}} </body> </html>
HTML
복사
이제 동작을 확인해보기 위해 클라이언트 앱으로 동작시켜보자!

GET

POST

Hello

이렇게 결과를 확인 할 수 있다.
이제 매번 JSON을 쓰고, 템플릿을 전하는게 귀찮기 때문에 간단하게 해주는 render 패키지를 추가한다.
설치 방법
github.com/unrolled/render
Plain Text
복사
사용법은 간단하다. 먼저 전역변수인 rd를 추가해준다.
var rd *render.Render
Go
복사
이렇게 하면 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) }
Go
복사
첫번째 인자가 ResponseWriter, 두번째 인자가 status, 세번째 인자가 JSON으로 바꾸고싶은 인스턴스이다. 이 한줄로 끝이 난다.
첫번째 인자가 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) }
Go
복사
Extensions이라는 옵션이 있는데 템플릿을 읽어올 때 어떤 확장자를 읽을지 알려주는 옵션이다.마찬가지로 디렉토리가 바뀔 수 있는데, 어떤 디렉토리를 읽고자 하는지 사용하는 옵션이다.
이번에는 템플릿에 어떤 레이아웃을 추가하는 것을 해보고자한다.저번 시간에 템플릿을 기능에 따라 2개 나누었듯이 나눠보자!

template/body.html

Name: {{.Name}} Email : {{.Email}}
HTML
복사
# template/hello.HTML를 body를 넣을 부분을 수정해주자!
<html> <head> <title>Hello Go in Web</title> </head> <body> Hello World {{ yield }} </body> </html>
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) }
Go
복사
body 템플릿에 넣어주기 위해 수정
이 상태에서 실행
정상적으로 작동 되는 것을 확인
body는 {{ yield }}로 템플릿을 지정했지만 title부분도 템플릿으로 지정해주고 싶다면 이렇게 수정해주면 된다.
<html> <head> <title>{{ partial "title" }}</title> </head> <body> Hello World {{ yield }} </body> </html>
HTML
복사
이렇게 만들어 준 뒤 title에 해당하는 템플릿을 만들면 된다!template/title-body.html
Partial Go in Web
Plain Text
복사
title-body라고 이름을 만들면 layout에서 해당 title에 해당하는 이름과 main.go의 body값을 읽은 부분을 채워주게 된다.
마지막으로 설치해볼 패키지는 negroni라는 패키지인데 HTTP 미들웨어이다.기본적으로 많이 쓰이는 부가기능들을 제공하는 패키지 라고 생각하면 된다.
go get github.com/urfave/negroni
Plain Text
복사
main.go를 수정하기 앞서 public 폴더에 index.html을 생성한다.
<html> <head> <title>Go in Web 11</title> </head> <body> <h1>Hello Go in Web</h1> </body> </html>
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 }
Go
복사
이걸 사용하면 핸들러가 하나 나온다.
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) }
Go
복사

template/body.html

Name: {{.Name}} Email: {{.Email}}
HTML
복사

template/hello.html

<html> <head> <title>{{ partial "title" }}</title> </head> <body> Hello World {{ yield }} </body> </html>
HTML
복사

template/title-body.html

Partial Go in Web
HTML
복사

public/index.html

<html> <head> <title>Go in Web 11</title> </head> <body> <h1>Hello Go in Web</h1> </body> </html>
HTML
복사