Сохраните проект в одной папке. Go рассматривает подпапки как отдельные пакеты. Вот пример приложения CMS: https://github.com/calebdoxsey/tutorials/tree/master/appengine/cms.
Я создал файл, который определяет маршруты в init
функции: (используя httprouter)
router.GET("/api/documents/:id", serveDocumentsGet)
В принципе каждая конечная точка получает свою собственную функцию:
func serveDocumentsGet(res http.ResponseWriter, req *http.Request, params httprouter.Params) {
serveAPI(res, req, func() interface{} {
ctx := appengine.NewContext(req)
session, _ := sessionStore.Get(req, "session")
email, ok := session.Values["email"].(string)
if !ok {
return HTTPError{403, "access denied"}
}
userKey := datastore.NewKey(ctx, "User", email, 0, nil)
docKey := datastore.NewKey(ctx, "Document", params.ByName("id"), 0, userKey)
var document Document
err := datastore.Get(ctx, docKey, &document)
if err != nil {
return err
}
return document
})
}
serveAPI
просто удобная функция для обрабатывать json-кодирование и ошибки:
func serveAPI(res http.ResponseWriter, req *http.Request, handler func() interface{}) {
res.Header().Set("Content-Type", "application/json")
result := handler()
if err, ok := result.(HTTPError); ok {
res.WriteHeader(err.Code)
json.NewEncoder(res).Encode(map[string]string{
"error": err.Message,
})
} else if err, ok := result.(error); ok {
res.WriteHeader(500)
json.NewEncoder(res).Encode(map[string]string{
"error": err.Error(),
})
} else if rc, ok := result.(io.ReadCloser); ok {
io.Copy(res, rc)
rc.Close()
} else {
json.NewEncoder(res).Encode(result)
}
}
В основном я стараюсь избегать магии, поэтому все конечные точки довольно явны.
Это дает вам контроллеры и модели (для более сложных моделей я разбиваю их на отдельные файлы ... см. Пример пользователя).
Для просмотра вы можете использовать встроенный шаблон шаблона шага. Создайте папку (возможно, static/tpl/yourtemplate.gohtml
) и используйте template.ParseFiles
и tpl.Execute
, чтобы сделать их. (еще раз это явно ... нет магии)
Но все чаще я нахожу, что большинство моих просмотров выполняются на стороне клиента с помощью javascript. Если вы сделаете это, то все, что вам нужно сделать, это служить файлы:
static := http.FileServer(http.Dir("static"))
router.GET("/static/*filepath", func(res http.ResponseWriter, req *http.Request, params httprouter.Params) {
filepath := params.ByName("filepath")
req.URL.Path = filepath
static.ServeHTTP(res, req)
})
Папки имеют очень разный смысловой смысл в Go, чем в Ruby. К сожалению, так же, как Rails не может быть применен к Go. – robbrit