Пользователь
1,7
рейтинг
10 декабря 2012 в 21:34

Разработка → Revel — высокопроизводительный веб-фреймворк на языке Go из песочницы

Язык Go Про язык программирования общего назначения Go я лично знаю довольно давно. Думаю, что многие из вас слышали о нем. Читая различные блоги, я находил описания экспериментов разработчиков с этой чудесной платформой (а это именно платформа, не только язык программирования в себе). Не знаю, почему, но я искренне полагал, что Go слишком молод для того, чтобы заострять на нем свое внимание. А зря. Как оказалось, в последнее время начали активно появляться замечательные прикладные библиотеки и фреймворки, которые лично мне, как веб-разработчику, чрезвычайно интересны, поскольку они сочетают в себе высокую производительность (все-таки, Go — это компилируемый язык) и относительную простоту в использовании. Об одном таком веб-фреймворке, написанном на Go, я и хочу рассказать. Итак, знакомьтесь, веб-фреймворк Revel.


Вначале я попрошу у сообщества некоторой снисходительности — я только-только начал погружение в Go, пользуюсь в основном информацией из зарубежных источников, и потому могу несколько путаться в русской терминологии. Тем не менее, надеюсь, что мой труд окажется кому-то полезным. Эта статья представляет собой, в основном, перевод официальной документации по фреймворку с некоторыми моими пояснениями.

Как явствует из главной страницы официального сайта, Revel — это реализация знакомого многим веб-фреймворка Play! на Go.

Подготовка окружения


Начнем с установки Go. Предполагается, конечно, что у вас Linux.

Установим переменную GOPATH


Если вы не создали эту переменную во время установки Go, сделайте это сейчас. GOPATH — это путь к корневой директории, где будут жить все ваши исходные коды Go. Чтобы создать эту переменную, проделаем следующее:

  1. Создадим директорию:
    mkdir ~/gocode
  2. Сообщим Go, чтобы он использовал эту директорию:
    export GOPATH=~/gocode
  3. Сохраним GOPATH, чтобы впоследствии эта переменная использовалась автоматически:
    echo GOPATH=$GOPATH >> .bash_profile


Все, на этом установка Go закончена.


Установим Git и Mercurial


Обе указанные системы контроля версий используются в Go для получения пакетов с помощью команды go get.



Установим Revel


go get github.com/robfig/revel

Во время выполнения этой команды произойдет несколько вещей:
  • Go, используя Git, склонирует репозиторий фреймворка в $GOPATH/src/github.com/robfig/revel/
  • Go последовательно разрешит все зависимости и установит необходимые пакеты, используя go get



Соберем Revel для использования из командной строки


Это поможет нам собирать, запускать и упаковывать наши приложения.

Для этого из директории GOPATH выполним следующую команду:
go build -o bin/revel github.com/robfig/revel/cmd


Добавим путь к бинарникам Revel к переменной PATH, чтобы использовать команды revel из любой директории
export PATH="$PATH:$GOPATH/bin"

echo 'PATH="$PATH:$GOPATH/bin"' >> .bash_profile


И, наконец, проверим, как все работает


$ revel help
~
~ revel! http://robfig.github.com/revel
~
usage: revel command [arguments]

The commands are:

    run         run a Revel application
    new         create a skeleton Revel application
    clean       clean a Revel application's temp files
    package     package a Revel application (e.g. for deployment)

Use "revel help [command]" for more information.


Ну все, теперь можем начинать творить.

Создадим приложение


И, конечно, воспользуемся нашей любимой командной строкой. Сначала создадим пустое приложение:
$ cd $GOPATH

$ revel new src/myapp
~
~ revel! http://robfig.github.com/revel
~
Your application is ready:
   src/myapp</pre>


Теперь запустим его:
$ revel run myapp
~
~ revel! http://robfig.github.com/revel
~
2012/09/27 17:01:54 run.go:41: Running myapp (myapp) in dev mode
2012/09/27 17:01:54 harness.go:112: Listening on :9000


Теперь откроем браузер, чтобы убедиться, что все работает



Структура файлов в приложениях Revel


gocode                  Корневая директория
app               
  controllers     Контроллеры
  models          Модели
  views           Шаблоны
tests             Тесты
conf              Конфиги
  app.conf        Основной файл конфигурации
  routes          Определения роутов
public            
  css             CSS
  js              Javascript
  images          Изображения


Директория /app


Директория app, как это обычно и бывает, содержит исходные коды нашего приложения: контроллеры, модели и шаблоны.
  • app/controllers
  • app/models
  • app/views



Revel следит за содержимым этой директории и, как только замечает изменения, перекомпилирует ваше приложение. Очень удобно. Но если изменения произойдут вне этой директории, Revel никак на них не отреагирует. Это уже задача разработчика.

Директория /public


Здесь хранятся статические файлы, и, как это обычно и случается, они разделены по трем вложенным директориям. Опять же, все довольно типично.

Директория /conf


Содержит файлы конфигурации. Два основных конфигурационных файла:
  • app.conf — файл с основными настройками приложения
  • routes — определения роутов



Роуты


Роуты, напомню, лежат у нас в файле conf/routes, который в нашем случае будет иметь следующее содержание:
GET     /                                       Application.Index


Как вы уже догадались, это означает, что в случае GET-запроса к «корню» сайта будет вызван метод Index в контроллере Application.

Контроллеры


Посмотрим содержимое этого контроллера. Файл находится в app/controllers/app.go:
package controllers

import "github.com/robfig/revel"

type Application struct {
	*rev.Controller
}

func (c Application) Index() rev.Result {
	return c.Render()
}


Все контроллеры должны быть унаследованы (если так можно выразиться в терминах Go) от rev.Controller или от *rev.Controller. Все методы-экшены контроллера должны возвращать rev.Result.

Контроллеры Revel поддерживают много удобных методов формирования результата запроса (Result). В указанном примере используется функция Render(), которая ищет соответствующий шаблон, парсит его и возвращает результат браузеру, попутно возвращая статус 200 ok.

Шаблоны


Все шаблоны должны лежать в папке app/views. Когда шаблон не указан явно, Revel берет шаблон, соответствующий экшену. Например, в нашем случае будет использован шаблон app/views/Application/Index.html:
{{set . "title" "Home"}}
{{template "header.html" .}}

<h1>Your Application Is Ready</h1>

{{template "footer.html" .}}


Помимо основных функций, которые используются в шаблонах Go, Revel добавляет ряд своих собственных. Указанный шаблон очень простой. Он:
  1. Задает тайтл страницы
  2. Инклудит шаблон хедера (я понимаю, что надо писать по-русски, но я не знаю, как это написать по-русски, чтобы не было коряво)
  3. Отображает приветствие
  4. Инклудит шаблон футера



Содержимое шаблона header.html выглядит таким образом:
<!DOCTYPE html>
<html>
  <head>
    <title>{{.title}}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" media="screen" href="/public/stylesheets/main.css">
    <link rel="shortcut icon" type="image/png" href="/public/images/favicon.png">
    <script src="/public/javascripts/jquery-1.5.2.min.js" type="text/javascript" charset="utf-8"></script>
    {{range .moreStyles}}
      <link rel="stylesheet" type="text/css" href="/public/{{.}}">
    {{end}}
    {{range .moreScripts}}
      <script src="/public/{{.}}" type="text/javascript" charset="utf-8"></script>
    {{end}}
  </head>
  <body>


Прекрасно видно, куда вставляется тайтл, а еще можно видеть, что шаблон принимает дополнительные файлы стилей и яваскриптов — обратите внимание на параметры moreStyles и moreScripts соответственно.

Приятные мелочи


Давайте изменим приветствие. Для этого отредактируем содержимое файда Index.html:
<h1>Your Application Is Ready</h1>


на:
<h1>Hello, world!</h1>


Теперь, если вы вновь откроете браузер и обновите нашу страницу, вы увидите, как ее содержимое изменилось. Revel отследил изменение шаблона и произвел его горячую перезагрузку. Он также отслеживает изменения в:
  • Содержимом директории app/
  • Шаблонах, находящихся внутри app/views/
  • Роутах, которые описаны в файле conf/routes



Изменения этих файлов будут автоматически учтены в Revel. Давайте посмотрим, что будет, если мы изменим содержимое нашего контроллера. Например, вот это:
return c.Render()


изменим на это:

return c.Renderx()


Мы намеренно допустили ошибку. Обновите страницу и вы увидите уведомление:

И напоследок давайте попробуем передать какие-нибудь данные в наш шаблон. Отредактируем наш контроллер:
return c.Renderx()


изменим на:
greeting := "Aloha World"
return c.Render(greeting)


Теперь файл шаблона. Изменим:
<h1>Hello, world!</h1>

на:
<h1>{{.greeting}}</h1>

Теперь обновим страницу и увидим, как Revel приветствует нас по-гавайски:

Несколько обнадеживающих выводов


Я довольно продолжительное время потратил на поиск платформы для разработки высоко производительных веб-приложений. Долгое время колебался, выбирая между «классикой» (например, Python с его Tornado), противоречивой Node.js (с его connect.js и express.js) и все еще являющимся экзотикой Erlang. Ситуация обостряется бесконечными холиварами вокруг этих платформ, особенно вокруг всего, что касается Node.js и Erlang. Холивары холиварами, но доля здравого смысла в нападках на Node.js, тем не менее, присутствует. Python я пока не рассматриваю в силу субъективных причин (о коих смысла писать нет — не хочу никого задеть), а Erlang — есть Erlang, он слишком экзотичный, хотя перед ним я испытываю уважение и трепет.

Я не утверждаю, что Go вцелом и Revel в частности являются панацеей или серебряной пулей. Но они, на мой взгляд, на эту серебряную пулю довольно сильно похожи, хотя недостатков тоже пока хватает. Например, отсутствие в Revel ORM (хотя этот недостаток легко восполняется наличием большого количества сторонних библиотек.

На данный момент Go — это очень мощный инструмент, обладающий всеми преимуществами компилируемых языков, да еще имеющий благородное происхождение. Думаю, что выбрав Go в качестве платформы для своего проекта, вы вряд ли пожалеете об этом в будущем. Тем более, что, как вы можете судить, интерес к языку есть, библиотеки появляются.

Кстати, если вас волнует вопрос запуска и работы Go под Windows — он прекрасно это умеет делать. Лично я сейчас практикуюсь именно под Windows (ну, так получилось).
Алексей Попов @Alexeyco
карма
10,0
рейтинг 1,7
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (39)

  • +6
    Отличный слог статьи, приятное чтение! Особенно интересно в таких обзорных статьях про новые технологии читать субъективное мнение и опыт автора, так что пишите ещё и побольше про плюсы и минусы, которые можно прочувствовать только в реальной работе.
    • +1
      Спасибо. Постараюсь поскорее выпустить продолжение, как только смогу убедиться, что правильно понимаю основные аспекты и практики платформы. Чтобы, знаете ли, не сбивать людей с толку и сразу помогать двигать в массы правильные принципы и подходы. Уж очень я проникся.
      • 0
        Спасибо за статью. Я не с целью критики, а просто подсказать — «инклюдить» можно выразить словом подключить или включить (вплане включить одну вещь в другую).
  • +3
    Адепты Go рекомендуют самому собирать веб-приложение по частям, используя стандартную библиотеку Go и Gorilla (например). По крайней мере те, которые сидят на канале #go-nuts в irc.freenode.net. И знаете, по-моему это действительно более правильный путь.
    • +1
      Я долго присматривался к горилле и мне этот тулкит тоже понравился. Хотя, конечно, это совершенно разные вещи. Revel подкупил меня лично несколько большей привычностью, что ли.

      Адепты Go рекомендуют самому собирать веб-приложение по частям, используя стандартную библиотеку Go и Gorilla (например)
      Вы имеете в виду соответствие такого подхода общей парадигме языка? Если так, то спасибо за наводку… приму на заметку. Очень мне понравился Go, почему-то… у него, наверное, карма хорошая. Сказывается происхождение.
      • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Даже так: для Go более каноничным считается подстраивать веб-интерфейс под архитектуру системы, нежели наоборот. Поэтому фреймворки косящие под Rails или Django и не в почёте :)
    • 0
      Я довольно упорно пытался найти хоть что-то, напоминающее «фреймворк», да к тому же, чтобы еще это было с хоть сколько-нибудь живым сообществом, и нашел только два — Revel и Gorilla. И то, последний — это вообще, строго говоря, и не фреймворк. Вероятно, потому, что мало кому требуется инструмент все-в-одном.

      Кстати, в первые дни погружения в Go не покидает ощущение некоторого запустения и таинственности: библиотек относительно мало (по сравнению с теми же Rails или npm), люди общаются с тобой тоже не очень охотно, в том же irc. Однако оно довольно быстро проходит, когда понимаешь, что так или иначе, все необходимое присутствует. Особенно когда речь идет о restful-приложениях, которым вообще мало что требуется. Думаю, это даже в некоторой степени и хорошо, что конкурентных библиотек не так много.

      Хотя я могу ошибаться на этот счет. Процесс погружения у меня еще далеко не закончен…
      • 0
        Gorilla — это именно тулкит. По сути просто набор пакетов, решающих каждый свою узкую задачу и не навязывающий чего либо.

        В этом вообще фишка Go: в простоте, ортогональности, когерентности. Никаких развесистых иерархий наследования, зато простой, но мощный и не связывающий руки embedding.
  • +1
    Внешне мне это все напомнило Play Framework 2.
    • 0
      Как явствует из главной страницы официального сайта, Revel — это реализация знакомого многим веб-фреймворка Play! на Go.
      :)
      • +1
        Который в свою очередь «Play is heavily inspired by Ruby on Rails and Django and is similar to this family of frameworks.» )
        • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Я довольно продолжительное время потратил на поиск платформы

    Было бы интересно узнать, к каким выводам вы пришли в результате поисков. Какие плюсы и минусы нашли для каждой из рассматриваемых платформ, применительно к вашему проекту.
    Тема py+tornado vs. js+node vs. go vs. erlang весьма животрепещуща, как показывают «напряженные» обсуждения в соответствующих статьях.
    • 0
      Я постараюсь ответить, но ответ, к сожалению, будет очень сильно субъективным. Прежде всего, связка tornado+python была отметена довольно быстро. Прошу понять меня правильно, но, к сожалению, я не могу сказать, почему именно… в целом, из-за субъективных причин. Хотя если бы этот вариант я тоже рассматривал, выбор был бы куда сложнее.

      Тем не менее, python+tornado был отметен, хотя я, опять же, не считаю, что это был бы плохой выбор. Остались два: node vs erlang, это слегка упростило задачу выбора, но опять же, не решило ничего. Если я начну рассуждения о том, что же лучше из этих двух вариантов, я могу снова породить лютый бешеный холивар, чего я совершенно не хочу.

      Кстати, я рассчитывал немного не на такой вопрос. Я думал, основным вопросом будет — почему не были рассмотрены варианты на Ruby, например. Или на Java…

      Тем не менее, ответ на все это один: совершенно случайно обстоятельства сложились таким образом, что я более глубоко познакомился с Go, и вопрос выбора отпал сам собой. По крайней мере, я пока так считаю.
  • 0
    Я не утверждаю, что Go вцелом и Revel в частности являются панацеей или серебряной пулей.


    А как вы определили, что этот фремворк действительно так производителен? Какие то тесты или другие источники?
    • +1
      Ну, например, есть вот этот пост многоуважаемого Дмитрия. Там есть ссылка на очень обстоятельный тест производительности. Да, там нет безусловного лидерства Go, но, сами понимаете, не синтетическими тестами едиными.
  • 0
    Тоже сейчас пишу маленький проектик на GO и именно на этом фремворке. Кстати у вас нет проблем с dev mode на windows? У меня в этом режиме все приложения что есть в примерах и каркас созданый через new не работают, то на одно грушат, то на другое. В prod режиме вроде работает все.

    Кстати go все-таки не хватает людей, судя по всему все проекты что есть в открытом доступе поддерживаются одним человеком и о помощи сообщества приходтся пока только мечтать.

    Кстати скоро новая версия go выйдет и там вроде как пофиксили проблемы на 32bit платформах.
    • 0
      Пока проблем не возникало. А если даже и возникнут, поставлю себе Debian какой-нибудь и буду крутить там. Все-таки, приложения надо разрабатывать в том окружении, в котором потом оно будет работать.
  • 0
    Благодаря этому посту я теперь знаю, что Суслик Го (так же известный как Гордон) дружит с Глендой…
  • +1
    Отличный язык статьи, и пунктуация соблюдена. Спасибо, автор!

    P.S. include вроде всегда было «подключить». Инклудит — подключает, вполне звучит. Не? Я всё же против такого жаргонизма в статьях, в устной речи — пожалуйста. Задает заголовок страницы. Подключает шаблон верхней секции html-документа (можно через апостроф: подключает шаблон header'а). Или тогда уже «Сетит тайтл пэйджа», «Инклудит темплэйт хедера» — чего стесняться? :)
  • 0
    И ещё у нас идешка есть — code.google.com/p/goclipse/
    А также несколько других standalone вариантов.
  • +1
    Вы меня заинтересовали языком Go, возьму его на заметку. Интересно, что его корни идут, в частности, от языка Limbo и в его проектировании участвовал один из создателей ОС Inferno, а до этого Unix — Кен Томпсон…
  • 0
    К чёрту работу… «ушёл играться с revel»

    P.S. очень рад что Go развивается! С полгода назад не смог найти подобного фреймворка и на этом изучение Go забросил.
  • 0
    Прошу прощения за глупый вопрос, но что делать если понадобится хост для готового продукта на этом фреймворке?
    • +1
      Да виртуалку в облаке поднять.
    • +1
      эммм… а в чем проблема? заказываете хвост и хвоститесь… например, vps-ку, разворачиваете линь, ставите go, ставите revel, заливаете проект, запускаете… profit!
      • +1
        Ну просто человек не понял, видимо, что значит «компилируемый язык»… Я, если честно, после всяких скриптовых языков, когда узрел работающий экзешник (простите меня, виндузятника непутевого), я, признаться, долгое время оглядывался по сторонам, щипал себя…
        • 0
          Возможно. Да я и сам дитя порока венды… )) так исторически сложилось… А сейчас вот пытаюсь усидеть на двух стульях, все такое вкусное, особенно в последние годы, так что в никсах я сам еще салага)
        • –1
          Однако не стоит забывать, что он включает в этот «экзешник» сам код интерпретатора + байт-код самой программы. Поэтому, по сравнению с «некомпилируемыми» языками, которые тем не менее кешируют байт-код профит не такой очевидный. Обратите внимани, что простой хелловорлд с одной строчкой в скомпилированном виде занимает ~4Мб Впрочем, все это не критично вообще.
          • +2
            нет в нем никакого интерпретатора и байт-кода
            FAQ
            Gccgo has a C++ front-end with a recursive descent parser coupled to the standard GCC back end.

            по поводу размера
            FAQ
            Why is my trivial program such a large binary?

            The linkers in the gc tool chain (5l, 6l, and 8l) do static linking. All Go binaries therefore include the Go run-time, along with the run-time type information necessary to support dynamic type checks, reflection, and even panic-time stack traces.

            A simple C «hello, world» program compiled and linked statically using gcc on Linux is around 750 kB, including an implementation of printf. An equivalent Go program using fmt.Printf is around 1.2 MB, but that includes more powerful run-time support.
            • –1
              Хм. А может раньше так было? Не могло ж мне такое само в голову взбрести. Хотя, в пять утра в субботу… :)
              В любом случае, спс за инфо!
              • –1
                И раньше не было
                • 0
                  Ну ок. Значит, перепутал. Прошу прощения, если кого-то ввел в заблуждение.

                  По теме: может быть вы вкратце расскажете, что входит в «more powerful run-time support»?
  • +2
    Вопрос такой, по поводу веб-сервера… Как я понимаю, в этой роли тут выступает имплементация http-сервера на Go?
    Если сравнивать с популярными веб-серверами, то какие есть преимущества/недостатки? В частности, в плане поддержки шифрования, кэширования, распределения нагрузки, отказоустойчивости и тп нюансы… Насколько оправдано использование в больших нагруженных проектах? И, как я понимаю, всегда есть возможность запустить взамен стандартного любой другой веб-сервер?

    Или я что-то не так понимаю?
    • +2
      Сколько всего. Попробую ответить, но вначале советую почитать официальный FAQ.

      Если сравнивать с популярными веб-серверами, то какие есть преимущества/недостатки?
      http — это именно пакет для работы с http, как и во многих других языках. Да, его можно назвать грубо «веб-сервером», но по большому счету, проще над ним ставить какой-нибудь nginx, чтобы огромную пачку проблем (упомянутое вами шифрование, кеширование, сжатие статики и т.д.) решить привычными способами. Как-то так.

      В общем, Go — это практически как Erlang, только Go.
  • +1
    собстна вопрос:
    ~/gocode$ go build -o bin/revel github.com/robfig/revel/cmd
    can't load package: package github.com/robfig/revel/cmd: cannot find package "github.com/robfig/revel/cmd" in any of:
    	/usr/local/go/src/github.com/robfig/revel/cmd (from $GOROOT)
    	/home/kuskov/gocode/src/github.com/robfig/revel/cmd (from $GOPATH)
    

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.