
Привет, Хабр!
Beego – это фреймворк для разработки веб-приложений на языке Go, ориентированный на быстрое развертывание и простоту использования. В его основе лежит идея создания полнофункциональных приложений с минимум усилиям на настройку и кодирование. Это достигается за счет широкого выбора инструментов, включая ORM, систему маршрутизации, интерфейс кмд и многое другое. Beego придерживается принципов package routers import ( "myapp/controllers" "github.com/beego/beego/v2/server/web" ) func init() { web.Router("/", &controllers.MainController{}) }
Для обработки запросов к корню сайта Пример параметризованной маршрутизации: Для обработки запросов к Контроллеры в Beego наследуются от Beego позволяет настраивать маршруты гибче, используя функции Пример группировки маршрутов: Создали пространство имен Также существуют перехватчики, которые позволяют выполнять код до или после определенных контроллеров: Также есть механизм авто-роутинга, который автоматически связывает URL-адреса с методами контроллеров на основе их имен: Так Beego будет автоматически маршрутизировать запросы типа Для решения более специфических задач, связанных с маршрутизацией, Beego позволяет настраивать роутер с помощью регулярных выражений и условий: Запросы к Beego суперски подходит для создания RESTful API благодаря своей системе маршрутизации. Можно определить маршруты для каждого из HTTP-методов (GET, POST, PUT, DELETE и т.д.) и связать их с соответствующими методами в контроллерах: Используя перехватчики, авто-роутинг, кастомные пути с регулярными выражениями и поддержку RESTful URL, можно идеально управлять потоками. ORM Beego позволяет отображать таблицы БД на структуры Go, превращая строки таблиц в объекты Go. Установим: В файле конфигурации приложения Beego В приложении (например, в Прочие БД подключаются аналогично. Для взаимодействия с БД понадобится определить модели. В Beego модели — это структуры Go, которые отражают структуру таблиц в базе данных. Пример простой модели пользователя: Чтобы использовать эту модель в Beego ORM её нужно зарегистрировать в системе ORM. Это делается так: После настройки подключения к БД и определения моделей можно приступить к операциям с данными. Чтобы создать новую запись в базе данных, используем Для чтения есть метод Для обновления записи апдейт: Для удаления записи Также есть транзакции, составные запросы, ленивая загрузка и т.д. Например, для выполнения транзакции: Также Beego ORM поддерживает работу с запросами через QueryBuilder: Beego использует систему шаблонов Go Шаблоны обычно хранятся в каталоге В контроллерах Beego можно передавать данные в шаблон, используя мапу Beego автоматически компилирует шаблоны и рендерит их при вызове метода Также есть возможность локализации с помощью поддержки i18n в пакете Файлы локализации хранятся в формате INI или JSON и содержат пары ключ-значение для переводов. По дефолту они размещаются в каталоге В Для использования локализации в шаблонах можно юзать функцию И в контроллерах можно использовать ту же функцию для получения локализованных строк программно: Язык для пользователя обычно определяется автоматически на основе заголовков HTTP-запроса, но его также можно задать явно, например, в зависимости от выбора пользователя на сайте. Тесты в Beego по дефолту размещаются в папке Допустим, у нас есть контроллер Определение контроллера: Создаем файл теста в папке Юзаем пакет Тесты в Beego, как и в любом Go-приложении, можно запустить с помощью команды Команда рекурсивно найдет и выполнит все тесты в вашем проекте Beego. А вот для тестирования API можно использовать пакет Пример контроллера API: Пример теста API: Создаем HTTP GET запрос к нашему API При тестировании компонентов, взаимодействующих с БД, нужно изолировать тесты от реальной БД. Это можно сделать с помощью мокинга или настройки тестовой БД: Юзаем SQLite в памяти для создания изолированной тестовой среды. Вставляем нового пользователя в тестовую БД и проверяем, что операция вставки прошла успешно, а возвращаемый идентификатор пользователя не равен нулю. В Beego сессии активируются в файле конфигурации После активации, сессии можно использовать прямо в контроллерах: Работа с куками также предельно упрощена: Настройка: Настраивает логирование в файл с определенным уровнем логирования. Beego позволяет определять спец. методы обработки ошибок в контроллерах: Beego интегрирован с Swagger, позволяя автоматически генерировать документацию для API. Для этого необходимо использовать комментарии к коду и инструмент Используя команду Beego упрощает стандартные задачи в создание веб-приложений. Больше про языки программирования эксперты OTUS рассказывают в рамках практических онлайн-курсов. С полным каталогом курсов можно ознакомиться по ссылке. / используется MainController.web.Router("/user/:id", &controllers.UserController{})/user/123, где 123 — это динамический параметр id, используется UserController.beego.Controller и содержат методы, соответствующие HTTP-методам Get, Post, Delete и т.д., которые вызываются при обращении к связанным с ними маршрутам. Пример контроллера:package controllers import "github.com/beego/beego/v2/server/web" type MainController struct { web.Controller } func (c *MainController) Get() { c.Data["Website"] = "Beego.me" c.Data["Email"] = "contact@beego.me" c.TplName = "index.tpl" }MainController обрабатывает GET-запросы. Данные, передаваемые в представление index.tpl, устанавливаются через c.Data.web.NSRouter, web.Include, и web.NSNamespace для группировки маршрутов и в целом более удобной организации приложений.ns := web.NewNamespace("/v1", web.NSRouter("/user", &controllers.UserController{}, "get:ListUsers"), web.NSRouter("/user/:id", &controllers.UserController{}, "get:GetUser"), ) web.AddNamespace(ns)/v1, в котором группируются маршруты, относящиеся к пользователям.web.InsertFilter("/user/*", web.BeforeExec, InterceptorFunc)InterceptorFunc будет вызываться перед каждым выполнением методов контроллера, обрабатывающего пути, соответствующие шаблону /user/*.web.AutoRouter(&controllers.YourController{})/yourcontroller/methodname к соответствующим методам в YourController.web.Router("/user/:id([0-9]+)", &controllers.UserController{})/user/123 будут обрабатываться UserController, при этом :id должен соответствовать регулярному выражению [0-9]+, что означает одну или более цифр.web.Router("/api/user", &controllers.UserController{}, "get:GetUsers;post:CreateUser") web.Router("/api/user/:id", &controllers.UserController{}, "get:GetUser;put:UpdateUser;delete:DeleteUser")Работа с БД
Подключение к БД на примере MySQL
go get -u github.com/go-sql-driver/mysqlconf/app.conf указываем параметры подключения к MySQL:[database] dbDriver = mysql dbUser = ваш_пользователь dbPass = ваш_пароль dbName = имя_базы_данных dbHost = 127.0.0.1 dbPort = 3306main.go) юзаем информацию из конфига для инициализации подключения к БД:import ( "github.com/beego/beego/v2/client/orm" _ "github.com/go-sql-driver/mysql" ) func init() { orm.RegisterDriver("mysql", orm.DRMySQL) // строка подключения: пользователь:пароль@tcp(хост:порт)/имя_базы_данных orm.RegisterDataBase("default", "mysql", "user:password@tcp(127.0.0.1:3306)/dbname") }Определение моделей
type User struct { Id int Name string Password string }func init() { orm.RegisterModel(new(User)) }Insert объекта ORM:o := orm.NewOrm() user := User{Name: "ivan", Password: "securepassword"} id, err := o.Insert(&user) if err != nil { // обработка ошибки }Read:o := orm.NewOrm() user := User{Id: 1} err := o.Read(&user) if err == orm.ErrNoRows { // зЗапись не найдена } else if err == nil { // запись найдена, `user` заполнен данными }o := orm.NewOrm() user := User{Id: 1, Name: "ivan Updated"} _, err := o.Update(&user, "Name") if err != nil { // обработка ошибки }Delete:o := orm.NewOrm() user := User{Id: 1} _, err := o.Delete(&user) if err != nil { // обработка ошибки }o := orm.NewOrm() err := o.Begin() user := User{Name: "Ivan Transaction", Password: "transpassword"} _, err = o.Insert(&user) if err != nil { o.Rollback() } else { o.Commit() }var users []User qb, _ := orm.NewQueryBuilder("mysql") qb.Select("id", "name").From("user").Where("id > ?").OrderBy("id").Desc().Limit(10) orm.NewOrm().Raw(qb.String(), 1).QueryRows(&users)Создание пользовательского интерфейса
html/template для динамической генерации HTML. Шаблоны позволяют разделять логику приложения и его представление.views и имеют расширение .tpl или .html. В шаблонах можно использовать конструкции Go Template для вставки данных, выполнения условий и циклов:<!-- views/index.tpl --> <html> <body> <h1>{{.Title}}</h1> {{range .Items}} <div>{{ . }}</div> {{else}} <div>No items found.</div> {{end}} </body> </html>Data.func (this *MainController) Get() { this.Data["Title"] = "My Page Title" this.Data["Items"] = []string{"Item 1", "Item 2", "Item 3"} this.TplName = "index.tpl" }ServeHTTP. Имя шаблона указывается в свойстве TplName контроллера.github.com/beego/beego/v2/server/web/i18n.conf/locale:// conf/locale/en-US.ini hello = "Hello" // conf/locale/ru-RU.ini hello = "Привет"main.go или в начальной функции приложения можно инициализровать i18n и указать директорию с файлами локализации:import "github.com/beego/beego/v2/server/web" func init() { web.SetStaticPath("/static", "static") web.AddFuncMap("i18n", web.I18n) web.LoadAppConfig("ini", "conf/app.conf") if err := web.LoadI18n("conf/locale"); err != nil { log.Fatal("Failed to load i18n files:", err) } }i18n.Tr.<body> <h1>{{i18n.Tr "en-US" "hello"}}</h1> </body>codefunc (this *MainController) Get() { locale := "ru-RU" // Обычно это значение извлекается из настроек пользователя или заголовков запроса greeting := web.I18n(locale, "hello") this.Data["Greeting"] = greeting this.TplName = "index.tpl" }Тестирование
tests проекта. MainController с методом Get, который возвращает простое сообщение. Пример теста для этого метода:// controllers/main.go package controllers import ( "github.com/beego/beego/v2/server/web" ) type MainController struct { web.Controller } func (c *MainController) Get() { c.Ctx.WriteString("Hello, Beego!") }tests, например, main_test.go:// tests/main_test.go package test import ( "net/http" "net/http/httptest" "testing" "github.com/beego/beego/v2/server/web" "path/filepath" "runtime" _ "yourapp/routers" "github.com/stretchr/testify/assert" ) func init() { _, file, _, _ := runtime.Caller(0) apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".." + string(filepath.Separator)))) web.TestBeegoInit(apppath) } func TestMainPage(t *testing.T) { r, _ := http.NewRequest("GET", "/", nil) w := httptest.NewRecorder() web.BeeApp.Handlers.ServeHTTP(w, r) assert.Equal(t, 200, w.Code) assert.Equal(t, "Hello, Beego!", w.Body.String()) }assert библиотеки testify для проверки, что ответ от сервера соответствует ожиданиям. Создаем HTTP-запрос к главной странице и проверяем, что статус-код ответа равен 200 и тело ответа содержит «Hello, Beego!».go test:go test ./...httptest. Предположим, есть API для получения информации о пользователях.// controllers/user.go package controllers import ( "encoding/json" "github.com/beego/beego/v2/server/web" ) type UserController struct { web.Controller } func (c *UserController) GetUser() { userId := c.Ctx.Input.Param(":id") user := User{Id: userId, Name: "Test User"} c.Data["json"] = &user c.ServeJSON() } type User struct { Id string `json:"id"` Name string `json:"name"` }// tests/api_test.go package test import ( "bytes" "net/http" "net/http/httptest" "testing" _ "yourapp/routers" "github.com/stretchr/testify/assert" ) func TestGetUser(t *testing.T) { req, err := http.NewRequest("GET", "/user/1", nil) if err != nil { t.Fatal(err) } rr := httptest.NewRecorder() web.BeeApp.Handlers.ServeHTTP(rr, req) assert.Equal(t, http.StatusOK, rr.Code) expected := `{"id":"1","name":"Test User"}` assert.Equal(t, expected, strings.TrimSpace(rr.Body.String())) }/user/1 и проверяем, что статус код ответа 200 OK и тело ответа соответствует ожидаемому JSON-объекту.func init() { orm.RegisterDataBase("default", "sqlite3", "file::memory:?mode=memory&cache=shared", 30) }func TestCreateUser(t *testing.T) { o := orm.NewOrm() o.Using("default") // user := &User{Name: "New User"} id, err := o.Insert(user) if err != nil { t.Errorf("Не удалось создать пользователя: %v", err) } assert.NotEqual(t, 0, id) }Прочие возможности
Работа с сессиями и куками
app.conf с использованием параметров sessionon, sessionprovider, и sessionname. Пример конфигурации для активации сессий:sessionon = true sessionprovider = "memory" sessionname = "beegosessionID"func (c *MainController) AnyMethodName() { // установка значения сессии c.SetSession("key", "value") // получение значения сессии value := c.GetSession("key") // удаление значения сессии c.DelSession("key") // уничтожение сессии c.DestroySession() }func (c *MainController) AnyMethodName() { // установка куки c.Ctx.SetCookie("name", "value", expire) // чтение куки value := c.Ctx.GetCookie("name") }Логирование
logs.SetLogger(logs.AdapterFile, `{"filename":"log/myapp.log"}`) logs.SetLevel(logs.LevelInfo)func (c *MainController) Error404() { c.Data["content"] = "Page not found" c.TplName = "404.tpl" }Автоматическая генерация документации API
bee для генерации документации:// @Title Get User // @Description get user by uid // @Param uid path int true "The key for staticblock" // @Success 200 {object} User // @Failure 403 :uid is empty // @router /:uid [get] func (u *UserController) Get() { // реализация метода }bee run -gendoc=true -downdoc=true, можно сгенерировать документацию Swagger, которая будет доступна по адресу /swagger приложения.
ссылка на оригинал статьи https://habr.com/ru/articles/802333/
Добавить комментарий