2015-05-01 3 views
3

Я только начинаю с Go, и в качестве первого проекта я решил создать простой сервер REST API. К сожалению, я столкнулся с проблемой, так как я не могу найти лучший способ структурирования своего проекта.Структура папок приложения REST в golang

До сих пор я использую ту же структуру, что и проект Rails, имея в виду наличие контроллеров и моделей в своих собственных папках, но это не так, как идиоматично, поскольку код go должен быть.

Есть ли у кого-нибудь советы о том, как правильно структурировать проект?

+0

Папки имеют очень разный смысловой смысл в Go, чем в Ruby. К сожалению, так же, как Rails не может быть применен к Go. – robbrit

ответ

-2

Сохраните проект в одной папке. 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) 
}) 
2

Это, вероятно, выполнимо, но из-за статическую компиляцию вы собираетесь иметь немного беспорядка, если вы хотите много Rails «автомат для определения маршрутов.

Возможно, у меня есть пакет models со всеми моделями баз данных, а затем что-то на основе Gorilla's mux, чтобы связать некоторые маршруты с некоторыми действиями.

Если все усложняется, вы можете попробовать более крупный фреймворк, такой как Revel, который может быть более подходящим для более крупного приложения MVC.

+0

Чем ты. Как бы вы справились с моделью и базой данных? Используете ли вы ORM или просто вызываете запросы к базе данных напрямую? – Aliou

 Смежные вопросы

  • Нет связанных вопросов^_^