Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

Top Go Web Frameworks

На гитхабе есть рейтинг веб-фреймворков, который можно посмотреть по ссылке:
Top Go Web Frameworks.

Его возглавляют 3 веб-фреймворка, которые будут рассмотрены в данной статье:
 gin
 beego
 echo
 

1. Gin

Начнем с gin.
Установка:
go get -u github.com/gin-gonic/gin

Документацию по API можно найти на godoc.org
Gin позиционирует себя как самый быстрый веб-фреймворк, который можно использовать для построения веб-приложений и сервисов. В нем реализована нестандартная маршрутизация, которая отсутсвует в станданртной библиотеке net/http.
Схема, по которой происходит обработка запроса в gin, выглядит следующим образом

Request -> Route Parser -> [Логика] -> Route Handler -> [Логика] -> Response

Первым делом мы парсим запрос и проверяем, есть ли данный путь в таблице маршрутов, и если есть, то вызывает для него обработчик.
Далее, чтобы не быть голословным, мы рассмотри конкретное веб-приложение, которое можно забрать отсюда:
gin app

Оно представляет из себя менеджер статей и имеет следующий функционал:
заводит пользователей, позволяет им создавать статьи, выводит список статей, а также отдельную статью.
Каждая статья к тому же доступна в любом из трех форматов - HTML, JSON, XML.
На примере этого приложения рассмотрим, как реализованы маршрутизация, рендер и аутентификация.
Маршрутизация используется для обработки запросов, приходящих на определенный урл. В gin используется быстрый маршрутизатор, который легко настраивается. Для маршрутизации можно использовать шаблоны и разбивать урлы по группам.
Главная страница, как обычно, обслуживается из корня. Пользовательские страницы будут обслуживаться (get, post) с префиксом u:
/u/login
/u/logout
/u/register

Урлы, обслуживающие запросы для статей, будут с префиксом article:
/article/create
/article/view/:article_id

Обработка запроса в go может быть реализована в различные моменты его жизни, как в начале, так и в конце, например для аутентификации или валидации. В этом приложении работа со статьями разрешена только авторизованным пользователям.
Веб-страницы используют html шаблоны. Здесь есть отдельные шаблоны для хидера, футера, меню, авторизации и т.д. Поддерживается вложенность шаблонов.
Основной шаблон - index.html - выглядит следующим образом:

 {{ template "header.html" .}}
   {{range .payload }}
     < a href="/article/view/{{.ID}}">
       {{ .Title }}
     < /a>
     {{.Content}}
   {{end}}
 {{ template "footer.html" .}}
 
Создание маршрутизатора:

 router := gin.Default()
 
Загрузка шаблонов:

 router.LoadHTMLGlob("templates/*")
 
Старт приложения

 router.Run()
 
Компилируем само приложение

 go build -o app
 
И запускаем

 ./app
 
Это приложение работает на порту 8080 по умолчанию. Страница, показывающая список статей, будет иметь следующий обработчик:

 func showIndexPage(c *gin.Context) {
   articles := getAllArticles()
   c.HTML(
     http.StatusOK,
     "index.html",
     gin.H{
       "title":   "Home Page",
       "payload": articles,
     },
   )
 }
 
где

 articles := getAllArticles()
 
Функция, которая в зависимости от контекста возвращает html, json или xml:

 func render(c *gin.Context, data gin.H, templateName string) {
   switch c.Request.Header.Get("Accept") {
   case "application/json":
     c.JSON(http.StatusOK, data["payload"])
   case "application/xml":
     c.XML(http.StatusOK, data["payload"])
   default:
     c.HTML(http.StatusOK, templateName, data)
   }
 }
 
Чтобы получить список статей в формате json, достаточно сделать запрос:

 curl -X GET -H "Accept: application/json" http://localhost:8080/
 
Соответственно для xml:

 curl -X GET -H "Accept: application/xml" http://localhost:8080/article/view/1
 
В данном приложении написаны unit-тесты для всех хэндлеров. Запустите команду:

 go test -v
 



2. Beego

Из достоинств это фреймворка можно особо выделить следующие:
1. ORM
2. Кеширование
3. Работа с сессиями

Также стоит отметить встроенную консольную утилиту bee, которая умеет:
1. Создавать новые приложения
2. Запускать приложения
3. Тестировать приложения

Установка beego:
go get github.com/beego/bee

Создадим новый проект:
>> bee new site
Его можно найти здесь:
$GOPATH/src/site
Там вы найдете следующую файловую структуру:

 site
 ├── conf
 │   └── app.conf
 ├── controllers
 │   └── default.go
 ├── models
 ├── routers
 │   └── router.go
 ├── static
 │   ├── css
 │   ├── img
 │   └── js
 ├── tests
 │   └── default_test.go
 ├── views
 │    └── index.tpl
 ├── main.go
 
Запускаем из этого каталога команду

 bee run
 
Если открыть файл controllers/default.go, то можно увидеть код:

 package controllers
 
 import (
 	"github.com/astaxie/beego"
 )
 
 type MainController struct {
 	beego.Controller
 }
 
 func (c *MainController) Get() {
 	c.Data["Website"] = "beego.me"
 	c.Data["Email"] = "astaxie@gmail.com"
 	c.TplName = "index.tpl"
 }
 
Добавим в него код:

 func (main *MainController) HelloSite() {
     main.Data["Website"] = "My Website"
     main.Data["Email"] = "your.email.address@example.com"
     main.Data["EmailName"] = "Your Name"
     main.Data["Id"] = main.Ctx.Input.Param(":id")
     main.TplNames = "site.tpl"
 }
 
Добавим в vievs/site.tpl код следующего содержания:

 < header class="hero-unit">
     < div class="container">
         < div class="row">
             < div class="hero-text">
                 < h1>Welcome to the Sitepoint / Beego App!
                 < h2>This is My Test Version
                     {{.Website}} {{.Email}} {{.EmailName}}
             < /div>
         < /div>
     < /div>
 < /header>
 
Добавим маршрут hello-world в router.go:

 func init() {
     beego.Router("/", &controllers.MainController{})
     beego.Router("/hello-world/:id([0-9]+)", &controllers.MainController{}, "get:HelloSite")
 }
 
Более полный пример можно забрать по адресу

 https://github.com/settermjd/Learning-Beego
 




3. Echo

Это один из самых минималистичных веб-фреймворков на go.

Установка:

 go get -u github.com/labstack/echo/...
 
Напишем Hello world. Создадим файл server.go:

 package main
 
 import (
 	"net/http"
 	"github.com/labstack/echo/v4"
 )
 
 func main() {
 	e := echo.New()
 	e.GET("/", func(c echo.Context) error {
 		return c.String(http.StatusOK, "Hello, World!")
 	})
     e.GET("/users/:id", getUser)
     e.GET("/show", show)
     e.POST("/save", save)
 	e.Logger.Fatal(e.Start(":1323"))
 }
 
 func getUser(c echo.Context) error {
   	// User ID from path `users/:id`
   	id := c.Param("id")
 	return c.String(http.StatusOK, id)
 }
 
 func show(c echo.Context) error {
 	// Get team and member from the query string
 	team := c.QueryParam("team")
 	member := c.QueryParam("member")
 	return c.String(http.StatusOK, "team:" + team + ", member:" + member)
 }
 
 func save(c echo.Context) error {
 	// Get name and email
 	name := c.FormValue("name")
 	email := c.FormValue("email")
 	return c.String(http.StatusOK, "name:" + name + ", email:" + email)
 }
 
Запускаем приложение:

 go run server.go
 
Наберем в другом терминале команду для сохранения пользователя:

 >> curl -F "name=Joe Smith" -F "email=joe@labstack.com" http://localhost:1323/save
 
Получим ответ:

 // => name:Joe Smith, email:joe@labstack.com
 
Для аплоада картинки создадим отдельный обработчик:

 func save(c echo.Context) error {
 	// Get name
 	name := c.FormValue("name")
 	// Get avatar
   	avatar, err := c.FormFile("avatar")
   	if err != nil {
  		return err
  	}
  
  	// Source
  	src, err := avatar.Open()
  	if err != nil {
  		return err
  	}
  	defer src.Close()
  
  	// Destination
  	dst, err := os.Create(avatar.Filename)
  	if err != nil {
  		return err
  	}
  	defer dst.Close()
  
  	// Copy
  	if _, err = io.Copy(dst, src); err != nil {
   		return err
   	}
 
 	return c.HTML(http.StatusOK, "Thank you! " + name + "")
 }
 
Наберем в другом терминале команду:

 >> curl -F "name=Joe Smith" -F "avatar=@/path/to/your/avatar.png" http://localhost:1323/save
 
После чего должны получить ответ:

 >> => Thank you! Joe Smith
 
В следующем примере разберем, как в связке с nginx сделать балансировку нагрузки между двумя экземплярами приложения, написанного на echo.
Сначала нужно настроить конфигурацию nginx:

 upstream localhost {
   server localhost:8081;
   server localhost:8082;
 }
 
 server {
   listen          8080;
   server_name     localhost;
   access_log      /var/log/nginx/localhost.access.log combined;
 
   location / {
     proxy_pass      http://localhost;
   }
 }
 
Перезапускаем nginx и убеждаемся, что все работает:

 service nginx restart
 
Запускаем два экземпляра нашего приложения (код ниже):

 go run server.go server1 :8081
 go run server.go server2 :8082
 
Если мы откроем адрес https://localhost:8080, то увидим либо- либо:

 Hello from upstream server server1
 
Код приложения - для простоты забиваем шаблон прямо сюда:

 package main
 
 import (
 	"fmt"
 	"net/http"
 	"os"
 
 	"github.com/labstack/echo"
 	"github.com/labstack/echo/middleware"
 )
 
 var index = `
 	< !DOCTYPE html>
 	< html lang="en">
 	< head>
 		< meta charset="UTF-8">
 		< meta name="viewport" content="width=device-width, initial-scale=1.0">
 		< meta http-equiv="X-UA-Compatible" content="ie=edge">
 		< title>Upstream Server< /title>
 		< style>
 			h1, p {
 				font-weight: 300;
 			}
 		< /style>
 	< /head>
 	< body>
 		< p>
 			Hello from upstream server %s
 		< /p>
 	< /body>
 	< /html>
 `
 
 func main() {
 	name := os.Args[1]
 	port := os.Args[2]
 	e := echo.New()
 	e.Use(middleware.Recover())
 	e.Use(middleware.Logger())
 	e.GET("/", func(c echo.Context) error {
 		return c.HTML(http.StatusOK, fmt.Sprintf(index, name))
 	})
 	e.Logger.Fatal(e.Start(port))
 }
 




Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье