Про язык программирования общего назначения Go я лично знаю довольно давно. Думаю, что многие из вас слышали о нем. Читая различные блоги, я находил описания экспериментов разработчиков с этой чудесной платформой (а это именно платформа, не только язык программирования в себе). Не знаю, почему, но я искренне полагал, что Go слишком молод для того, чтобы заострять на нем свое внимание. А зря. Как оказалось, в последнее время начали активно появляться замечательные прикладные библиотеки и фреймворки, которые лично мне, как веб-разработчику, чрезвычайно интересны, поскольку они сочетают в себе высокую производительность (все-таки, Go — это компилируемый язык) и относительную простоту в использовании. Об одном таком веб-фреймворке, написанном на Go, я и хочу рассказать. Итак, знакомьтесь, веб-фреймворк Revel.
Вначале я попрошу у сообщества некоторой снисходительности — я только-только начал погружение в Go, пользуюсь в основном информацией из зарубежных источников, и потому могу несколько путаться в русской терминологии. Тем не менее, надеюсь, что мой труд окажется кому-то полезным. Эта статья представляет собой, в основном, перевод официальной документации по фреймворку с некоторыми моими пояснениями.
Как явствует из главной страницы официального сайта, Revel — это реализация знакомого многим веб-фреймворка Play! на Go.
Подготовка окружения
Начнем с установки Go. Предполагается, конечно, что у вас Linux.
Установим переменную GOPATH
Если вы не создали эту переменную во время установки Go, сделайте это сейчас. GOPATH — это путь к корневой директории, где будут жить все ваши исходные коды Go. Чтобы создать эту переменную, проделаем следующее:
- Создадим директорию:
mkdir ~/gocode
- Сообщим Go, чтобы он использовал эту директорию:
export GOPATH=~/gocode
- Сохраним 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>
</p>
<p>Теперь запустим его: <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.
Шаблоны
All templates are kept in the directory. When an explicit template name is not specified, Revel looks for a template matching the action. In this case, Revel finds the app/views/Application/Index.html file, and renders it as a Go template.
Все шаблоны должны лежать в папке 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 добавляет ряд своих собственных. Указанный шаблон очень простой. Он:
- Задает тайтл страницы
- Инклудит шаблон хедера (я понимаю, что надо писать по-русски, но я не знаю, как это написать по-русски, чтобы не было коряво)
- Отображает приветствие
- Инклудит шаблон футера
Содержимое шаблона 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