[Go] Go: Как подключить внешнюю библиотеку и исключить ненужные зависимости (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
TL;DR: Кодогенератор.
Представьте, что вы разрабатываете некоторую библиотеку, которая поддерживает различные драйвера для хранения данных: Postgresql, Scylla, JSON и какие-либо другие.
У каждого из этих драйверов есть внешние зависимости от других библиотек. Postgresql — database/sql, github.com/lib/pq. Scylla — github.com/scylladb/gocql или стандартный github.com/gocql/gocql. JSON — github.com/mailru/easyjson или github.com/json-iterator/go, или encoding/json.
Обычный пользователь подключает вашу библиотеку и получает неявное включение всех этих внешних библиотек.
В большинстве случаев это нормально, но не идеально: иногда пользователю нужен только Postgres драйвер, но вместе с ним он неявно получает огромное количество кода из внешних библиотек, которые ему никогда не будут нужны.
Попробуем это исправить, используя замечательный механизм кодогенерации.
Кодогенерация
Разбейте файлы на части
Разбейте файлы вашей библиотеки на логические части, которые реализуют каждую отдельную конкретную зависимость. Пример: sql.go, cql.go, json.go.
Это позволит вам сгенерировать для пользователя только ту часть вашей библиотеки, которую он запросит.
Упакуйте файлы
Упакуйте файлы через pkger или любое другое решение для хранения их в бинарном файле.
Для включения файлов через pkger — в исходном коде просто нужно их использовать
files := make([]string, 0)
if *cql {
files = append(files, pkger.Include("/cql.go"))
}
if *json {
files = append(files, pkger.Include("/json.go"))
}
if *sql {
files = append(files, pkger.Include("/sql.go"))
}
Далее запустите
pkger -o <путь к исходнику кодогенератора>
И после этого вы получите статический исходник с упакованными файлами, который будут включены в бинарный файл.
Удобно добавить генерацию в go generate
//go:generate pkger -o <путь к исходнику кодогенератора>
Упаковка исходных кодов в бинарный файл нужна потому, что кодогенератор будет использоваться независимо от вашей библиотеки.
Напишите кодогенератор
Кодогенератор — это обычная программа на Go, которая принимает аргументы для генерации и записывает исходные файлы для выбранных типов в проект пользователя.
for i := range files {
_, filename := filepath.Split(files[i])
in, err := pkger.Open(files[i])
if err != nil {
panic(err)
}
src := []byte(fmt.Sprintf(genStr, strings.Join(os.Args[1:], " ")))
reader := bufio.NewReader(in)
for {
line, err := reader.ReadBytes('\n')
if strings.HasPrefix(string(line), "package ") {
line = []byte(fmt.Sprintf("package %s\n", *pkgName))
}
src = append(src, line...)
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
}
if err := ioutil.WriteFile(filename, src, 0644); err != nil {
panic(err)
}
in.Close()
}
Разместите исходный код вашего кодогенератора в подпапке проекта вида “cmd/<имя вашего проекта>”. Это позволит пользователю получить бинарный файл кодогенератора с тем же названием, что и название вашей библиотеки.
Использование
Пользователь устанавливает кодогенератор
go get github.com/<ваш профиль>/<ваша библиотека>/<путь к кодогенератору>
И затем запускает кодогенератор в своём проекте
<имя бинарного файла вашего кодогенератора> -sql
Когда нужно обновить вашу библиотеку — пользователь обновляет кодогенератор
go get -u github.com/<ваш профиль>/<ваша библиотека>/<путь к кодогенератору>
И затем запускает генерацию заново.
Пример данного подхода к использованию зависимостей я и creker реализовали в библиотеке nan: с библиотекой можно работать как в обычном режиме, через import, так и в варианте кодогенерации.
===========
Источник:
habr.com
===========
===========
Автор оригинала: Rallar
===========Похожие новости:
- [Godot, Разработка игр] Механики для реализации платформера на Godot engine. 2 часть
- [Разработка игр, Godot] Механики для реализации платформера на игровом движке GodotEngine
- [Веб-дизайн, Разработка веб-сайтов, Google Web Toolkit, Поисковая оптимизация, Голосовые интерфейсы] Современное SEO: качество страниц
- [Go, Управление персоналом] Коллеги, вы меня огорчаете
- [Законодательство в IT, IT-компании] Китай грозит Google антимонопольной проверкой за Android
- [Программирование, Анализ и проектирование систем, Проектирование и рефакторинг, Промышленное программирование] Шаблоны GRASP: Polymorphism, Pure Fabrication, Indirection, Protected Variations
- [Краудсорсинг, Игры и игровые приставки] Спонсорам Atari VCS отправляют первую партию консолей
- [Веб-аналитика, Интернет-маркетинг, Контекстная реклама, Повышение конверсии] Как узнать, сколько трафика идет по скрытым запросам в Google Ads [скрипт]
- [MongoDB, Администрирование баз данных] Виды репликации в MongoDB
- [Серверная оптимизация, Серверное администрирование, Хранение данных, Хранилища данных] Я был неправ. Будущее за CRDT (перевод)
Теги для поиска: #_go, #_codegen, #_go
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:07
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
TL;DR: Кодогенератор. Представьте, что вы разрабатываете некоторую библиотеку, которая поддерживает различные драйвера для хранения данных: Postgresql, Scylla, JSON и какие-либо другие. У каждого из этих драйверов есть внешние зависимости от других библиотек. Postgresql — database/sql, github.com/lib/pq. Scylla — github.com/scylladb/gocql или стандартный github.com/gocql/gocql. JSON — github.com/mailru/easyjson или github.com/json-iterator/go, или encoding/json. Обычный пользователь подключает вашу библиотеку и получает неявное включение всех этих внешних библиотек. В большинстве случаев это нормально, но не идеально: иногда пользователю нужен только Postgres драйвер, но вместе с ним он неявно получает огромное количество кода из внешних библиотек, которые ему никогда не будут нужны. Попробуем это исправить, используя замечательный механизм кодогенерации. Кодогенерация Разбейте файлы на части Разбейте файлы вашей библиотеки на логические части, которые реализуют каждую отдельную конкретную зависимость. Пример: sql.go, cql.go, json.go. Это позволит вам сгенерировать для пользователя только ту часть вашей библиотеки, которую он запросит. Упакуйте файлы Упакуйте файлы через pkger или любое другое решение для хранения их в бинарном файле. Для включения файлов через pkger — в исходном коде просто нужно их использовать files := make([]string, 0)
if *cql { files = append(files, pkger.Include("/cql.go")) } if *json { files = append(files, pkger.Include("/json.go")) } if *sql { files = append(files, pkger.Include("/sql.go")) } Далее запустите pkger -o <путь к исходнику кодогенератора>
И после этого вы получите статический исходник с упакованными файлами, который будут включены в бинарный файл. Удобно добавить генерацию в go generate //go:generate pkger -o <путь к исходнику кодогенератора>
Упаковка исходных кодов в бинарный файл нужна потому, что кодогенератор будет использоваться независимо от вашей библиотеки. Напишите кодогенератор Кодогенератор — это обычная программа на Go, которая принимает аргументы для генерации и записывает исходные файлы для выбранных типов в проект пользователя. for i := range files {
_, filename := filepath.Split(files[i]) in, err := pkger.Open(files[i]) if err != nil { panic(err) } src := []byte(fmt.Sprintf(genStr, strings.Join(os.Args[1:], " "))) reader := bufio.NewReader(in) for { line, err := reader.ReadBytes('\n') if strings.HasPrefix(string(line), "package ") { line = []byte(fmt.Sprintf("package %s\n", *pkgName)) } src = append(src, line...) if err == io.EOF { break } if err != nil { panic(err) } } if err := ioutil.WriteFile(filename, src, 0644); err != nil { panic(err) } in.Close() } Разместите исходный код вашего кодогенератора в подпапке проекта вида “cmd/<имя вашего проекта>”. Это позволит пользователю получить бинарный файл кодогенератора с тем же названием, что и название вашей библиотеки. Использование Пользователь устанавливает кодогенератор go get github.com/<ваш профиль>/<ваша библиотека>/<путь к кодогенератору>
И затем запускает кодогенератор в своём проекте <имя бинарного файла вашего кодогенератора> -sql
Когда нужно обновить вашу библиотеку — пользователь обновляет кодогенератор go get -u github.com/<ваш профиль>/<ваша библиотека>/<путь к кодогенератору>
И затем запускает генерацию заново. Пример данного подхода к использованию зависимостей я и creker реализовали в библиотеке nan: с библиотекой можно работать как в обычном режиме, через import, так и в варианте кодогенерации. =========== Источник: habr.com =========== =========== Автор оригинала: Rallar ===========Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:07
Часовой пояс: UTC + 5