Golang → go-chi: Генерация URL по имени роута

Пересадил свой блог с gorilla/mux на go-chi и в процессе переделывания обнаружил два момента:

  • В go-chi нет генерации урлов из коробки
  • gorilla/mux уже не заброшенный проект, у него появилась новая команда мантейнеров

Последний пункт, в принципе, сделал задачу по замене роутера ненужной, ведь я менял его потому, что gorilla/mux не поддерживается, но меня было уже не остановить, ведь процесс программирования тоже важен, а не только конечный результат 😊

Быстрое гугление по запросу "go-chi generate url by name" привело меня в issue #209, где я наткнулся на пакет reverse от alehano и который походил на то, что я уже задумал сделать для решения этой задачи по генерации урлов. Оставалось только форкнуть этот пакет и модифицировать в соответствии со своим видением, каким этот reverse должен быть → github.com/xelbot/reverse

Приведу пару примеров. Код без реверса, исходный:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
	"net/http"

	"supersite/handlers"
	"github.com/go-chi/chi/v5"
)

func main() {
	r := chi.NewRouter()
	r.Get("/article/{slug}", handlers.ArticleAction)
	r.Get("/avatar/{hash:[0-9A-Z]+}.png", handlers.Avatar)

	http.ListenAndServe(":8000", r)
}

Этот же фрагмент, но уже с реверсом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"net/http"

	"supersite/handlers"
	"github.com/go-chi/chi/v5"
	"github.com/xelbot/reverse"
)

func main() {
	r := chi.NewRouter()
	r.Get(reverse.Add("article", "/article/{slug}"), handlers.ArticleAction)
	r.Get(reverse.Add("avatar", "/avatar/{hash:[0-9A-Z]+}.png"), handlers.Avatar)

	http.ListenAndServe(":8000", r)
}

Генерация урла происходит в стиле gorilla/mux, с передачей имени роута и строковыми парами имя параметра/значение:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
url, err := reverse.Get("article", "slug", "url-generation")
if err != nil {
	panic(err)
}

// url: /article/url-generation

url2, err := reverse.Get("avatar", "hash", "A3B2C1")
if err != nil {
	panic(err)
}

// url2: /avatar/A3B2C1.png

Поддерживаются и суброуты, т.е. группы роутов, с общим префиксом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
r := chi.NewRouter()
r.Route(reverse.Group("group-art", "/articles"), func(r chi.Router) {
	r.Get(reverse.AddGr("search", "group-art", "/search"), searchArticles)
	r.Get(reverse.AddGr("article", "group-art", "/{year}/{slug:[a-z-]+}"), getArticle)
})

url1, _ := reverse.Get("search")
url2, _ := reverse.Get("article", "slug", "hi-there", "year", "2024")

// url1: /articles/search
// url2: /articles/2024/hi-there

Комментарии

0 комментариев Написать что-нибудь
Или войдите, чтобы не заполнять форму:
Адрес электронной почты нигде не отображается, необходим только для обратной связи.
Напрограммировано на Go 1.23.2, версия движка 7738e0f