Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6507 
 Linux Kernel 2.6...5279 
 Trees...1119 
 Максвелл 3...1051 
 William Gropp...990 
 Go Web ...963 
 Ethreal 3...930 
 Ethreal 4...918 
 Gary V.Vaughan-> Libtool...914 
 Ext4 FS...905 
 Clickhouse...901 
 Rodriguez 6...900 
 Ethreal 1...897 
 Steve Pate 1...886 
 C++ Patterns 3...864 
 Assembler...854 
 Ulrich Drepper...844 
 DevFS...788 
 MySQL & PosgreSQL...774 
 Стивенс 9...758 
 
  01.01.2024 : 3621733 посещений 

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))
 }
 




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

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

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