Go: создание веб-приложения с помощью Beego

Эта статья является первой из двух частей цикла «Создание веб-приложений с помощью Beego»:

Создание веб-приложений с помощью Beego

Вступление

Вы разработчик веб-приложений, желающий перейти на Go с динамического языка программирования PHP, Python или Ruby, и вы интересуетесь, как создавать веб-приложения с его использованием? Вы задаетесь вопросом, как развивать приложения приблизительно так же, как в этих фреймворках, используя имеющиеся у вас знания?

Если да, то вы, вероятно, уже потратили какое-то время на поиск информации в Google, StackOverflow или на других сайтах. И вы, вероятно, уже увидели, что существует целый ряд подходящих вариантов, в том числе Beego, Martini и Gorilla; это не считая пакета net/http.

Из четырех названных фреймворков я довольно много экспериментировал с Beego. Я увидел, что он вполне функционален, и в то же время не слишком сложен, так что я довольно быстро освоился в нем.

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

  • Полное объектно-реляционное отображение;
  • Кэширование;
  • Поддержку сессий;
  • Мультиязычный интерфейс;
  • Мониторинг и перезагрузку в режиме реального времени;
  • Поддержку развертывания проектов.

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

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

В этой серии статей я расскажу вам о том, что делает Beego таким прекрасным фреймворком, и как много возможностей он открывает для разработчиков. В частности, в этой первой части мы рассмотрим:

  • Установку Beego и инструмент командной строки Bee;
  • Создание проекта;
  • Действия;
  • Представления / Шаблоны;
  • Маршрутизацию;
  • Параметры запросов.

Если вы хотите просмотреть завершенный код для этой серии статей, он доступен на Github. Вы можете ознакомиться с ним или клонировать сам код и поэкспериментировать с ним. Приступим!

Прежде чем начать, убедитесь, что ваша GO среда настроена соответствующим образом. Если нет или вы понятия не имеете, что я имею в виду, ознакомьтесь с руководством Приступая к работе с Go или с этой статьей Билла Кеннеди, а затем возвращайтесь, и мы продолжим.

1. Установка Beego

Ок, давайте начнем с установки Beego. Как и целый ряд фреймворков и средств разработки, Beego поддерживает встроенные механизмы управления через командную строку bee.

Bee может:

  • Создавать новые приложения;
  • Запускать приложения;
  • Тестировать приложения;
  • Создавать маршруты и т.д.

Bee — это не единственный доступный способ запуска приложений Beego, но именно его я буду использовать на протяжении этой серии статей. Чтобы установить его, выполните go get github.com/beego/bee.

2. Создание проекта ядра

После установки из вашей папки $GOPATH выполните следующую команду, которая будет разворачивать приложение под названием sitepointgoapp:

bee new sitepointgoapp

На экране вы увидите что-то похожее на это:

[INFO] Creating application...
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/conf/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/controllers/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/models/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/routers/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/tests/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/static/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/static/js/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/static/css/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/static/img/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/views/
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/conf/app.conf
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/controllers/default.go
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/views/index.tpl
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/routers/router.go
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/tests/default_test.go
/Users/matthewsetter/Documents/workspace/Golang/src/sitepointgoapp/main.go
14-05-14 06:02:59 [SUCC] New application successfully created!

Сейчас у нас создана следующая структура каталогов:

структура каталогов

Просматривая эти файлы, мы можем увидеть, что у нас теперь есть:

  • Наш загрузочный файл main.go;
  • Основной файл конфигурации conf/app.conf;
  • Контроллер по умолчанию controllers/default.go;
  • Набор тестов по умолчанию в tests/default_test.go;
  • Шаблон представления по умолчанию в views/index.tpl;

Правильно, базовое приложение готово к работе, давайте запустим его. Из директории проекта $GOPATH/src/sitepointgoapp/ выполните следующую команду:

bee run

Она загружает наше новое приложение. В качестве дополнительного бонуса bee производит проверку исходных файлов на предмет обновлений. Если обновления будут обнаружены, bee автоматически перезагрузит приложение. После выполнения приведенной выше команды вы должны увидеть на экране что-то похожее на это:

14-05-05 11:34:17 [INFO] Start building...
14-05-05 11:34:20 [SUCC] Build was successful
14-05-05 11:34:20 [INFO] Restarting sitepointgoapp ...
14-05-05 11:34:20 [INFO] ./sitepointgoapp is running...
2014/05/05 11:34:20 [I] Running on :8080

Вы можете видеть, что приложения готовы к запуску через порт 8080. Загрузка в браузере адреса http://localhost:8080/ должна вывести на экране следующее:

Загрузка в браузере адреса

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

3. Добавление нового действия

Открыв файл controllers/default.go, вы увидите практически пустой контроллер. Это потому, что вся логика вывода содержится в шаблоне представления. Давайте немного поменяем содержимое контроллера и посмотрим, как добавить переменные шаблона представления и указать файл шаблона.

В файл default.go добавьте следующий метод:

func (main *MainController) HelloSitepoint() {
    main.Data["Website"] = "My Website"
    main.Data["Email"] = "your.email.address@example.com"
    main.Data["EmailName"] = "Your Name"
    main.TplNames = "default/hello-sitepoint.tpl"
}

Давайте по шагам разберем, что этот код означает. Указав main *MainController в качестве получателя метода, мы добавили новый метод (или действие) Get в текущий контроллер.

После этого мы инициализировали три переменных шаблона, Website, Email и EmailName, сохранив их в поле в контроллере, и вызвав Data, которая является картой, представляющей переменные и значения шаблона.

После этого, я указал имя файла шаблона, установив this.TplNames для default/hello-sitepoint.tpl. Если вам интересно, по умолчанию Beego будет искать указанный файл в директории views.

Поэтому, когда выполняется этот маршрут, Beego будет извлекать файл views/default/hello-sitepoint.tpl и воспроизводить его.

Представления

Правильно, давайте создадим прилагаемое представления. В директории default создайте новую директорию default и в ней новый файл hello-sitepoint.tpl, вставив в него следующий код:

<header class="hero-unit">
    <div class="container">
        <div class="row">
            <div class="hero-text">
                <h1>Welcome to the Sitepoint / Beego App!</h1>
                <h2>This is My Test Version</h2>
                <p>{{.Website}} {{.Email}} {{.EmailName}}</p>
            </div>
        </div>
    </div>
</header>

Если это ваш первый опыт работы с шаблонами Go, знайте, что структура шаблона Beego расширяет пакет html/шаблон Go. Здесь вы найдете несколько примеров использования переменных в шаблонах.

Как и большинство пакетов Go, пакет html/шаблон достаточно велик, поэтому я буду рассказывать только о его отдельных особенностях. Все переменные шаблона доступны в глобальном контексте, доступ к ним можно получить через оператор точки, встроенный с помощью синтаксиса {{}}.

Таким образом, чтобы получить доступ к трем переменным шаблона, которые мы ранее задали в действии контроллера, мы ссылаемся на них следующим образом:

{{.Website}}, {{.Email}} и {{.EmailName}}.

Маршрутизация

Отлично, у нас есть новое действие и соответствующее ему представление. Но мы пока еще не можем выполнить маршрут. Если бы мы попытались получить доступ к чему-либо, кроме действия по умолчанию, мы бы увидели на экране страницу ошибки 404 по умолчанию, как это показано на скриншоте ниже:

Маршрутизация

Итак, нам нужно добавить маршрут. В файле routers/router.go отредактируйте метод инициализации, чтобы он выглядел следующим образом:

func init() {
    beego.Router("/", &controllers.MainController{})
    beego.Router("/hello-world", &controllers.MainController{}, "get:HelloSitepoint")
}

Давайте рассмотрим подробнее последнюю строку. В ней в контроллере MainController вызывается действие HelloSitepoint, когда мы пытаемся направить пользователя на страницу /hello-world. Сохраните изменения и подождите немного, пока завершится рекомпиляция.

Затем перейдите в браузере по адресу http://localhost:8080/hello-world. Если все хорошо, то на экране вы должны увидеть следующее:

увидеть следующее

Параметры запроса

То, что мы делали до сих пор, отлично подходит для простых действий. Но в реальных приложениях, мы будем иметь дело с взаимодействиями с запросами, проверками строки запроса или POST-данными, а затем приложение должно будет выполнять соответствующие действия. Так как же нам получить доступ к этой информации с помощью Beego?

Давайте начнем с извлечения данных из строки запроса. Еще одним из предварительно назначенных значений в Beego является контекстный модуль, который содержит значение Input, которое, в свою очередь, инкапсулирует запрос.

Это позволяет нам получить доступ к таким компонентам, как:

  • метод;
  • протокол;
  • агент пользователя;
  • запрос (получение и отправка данных);
  • информация о сессии и т.д.

Давайте, чтобы было немного интереснее, изменим затребование значения идентификатора, установив его таким образом, чтобы мы могли вывести на экран и просмотреть действие. В файле router.go измените маршрут /get следующим образом:

beego.Router("/hello-world/:id([0-9]+)", &controllers.MainController{}, "get:HelloSitepoint")

Теперь, мы должны указать значение GET, которое может являться только числом, исходя из регулярного выражения, которое мы задали в маршруте, ([0-9]+). Сохраните изменения, и теперь попробуйте загрузить /hello-world без идентификатора. Вам выдается ошибка?

Теперь перейдите по адресу в /hello-world/213, все должно работать. А теперь, давайте получим информацию. В методе GET выше this.TplNames вставьте следующий код:

this.Data["Id"] = this.Ctx.Input.Param(":id")

И после этого в файле hello-world.tpl вставьте следующий код после существующей переменной шаблона: {{.Id}}. Перезагрузите страницу и вы увидите, что теперь после адреса электронной почты выводится число 213.

Ограничительные действия для типов методов

Хорошо, на сегодня мы почти закончили, но, прежде чем попрощаться, я хочу затронуть еще одну вещь. Часто нам нужно ограничить доступ к действию для одного или более конкретных методов. Например, вы захотите предоставить доступ на удаление маршрута только через POST-запрос; вы можете захотеть отображать результаты поиска только по запросу GET.

Beego позволяет легко сделать это, обеспечив доступ к действию для всех типов методов, или наоборот, ограничив доступ, открыв его только одному или нескольким типам методов. Опять же в файле router.go измените маршрут /hello-world следующим:

beego.Router("/hello-world/:id([0-9]+)", &controllers.MainController{}, "get,post:Get")

Таким образом, мы разрешаем выполнять действия по запросам как GET, так и POST.

Попробуйте, используя приведенные ниже примеры, поменять типы на PUT или DELETE и посмотрите, что у вас получится:

# PUT request
curl -X PUT http://localhost:8080/hello-world/213

# DELETE request
curl -X DELETE http://localhost:8080/hello-world/213

Заключение

Я надеюсь, вам понравилось это представление фреймворка Beego для создания веб-приложений. В следующей статье мы будем интегрировать базу данных (SQLite3), рассмотрим модели формы и валидацию.

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

Хотя Beego и Go отличаются от динамических языков программирования вы, возможно извлечете пользу из их использования. Вам потребуется совсем немного времени и усилий, чтобы освоить их, и задействовать все возможности, которые они открывают перед вами.

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

Что вы думаете об этом? Достаточно ли этой информации, чтобы начать работать с Go? Поделитесь своими мыслями в комментариях.

Перевод статьи «Go: Building Web Applications with Beego» был подготовлен дружной командой проекта Сайтостроение от А до Я.