Студенты, которые пишут бэкенд-бизнес, часто высмеивают, что их работа — это CRUD вокруг таблиц данных.Хотя реальная работа не так проста, в повседневной жизни действительно много похожей повторяющейся и нетворческой работы. И эту работу можно в определенной степени автоматизировать. Чтобы повысить эффективность развития персонала отдела исследований и разработок, мы некоторое время назад разработали инструмент рабочего процесса для серверной разработки, который в основном обеспечивает следующие функции:
- Генерировать базовый код API сервера и комментарии к документации Swagger (поддерживается только фреймворк gin)
- Сгенерировать клиентский код API сервера
- go struct добавляет теги партиями
- Сгенерировать структуру модели горма
- структура модели генерирует sql
Поскольку эти функции связаны с нашей внутренней общедоступной библиотекой, исходный код всего инструмента может быть закрыт. Здесь мы беремmodel struct 生成 sql
Возьмем функцию в качестве примера, давайте поговорим о наших идеях и инструментах, использованных при создании этого инструмента.
Задача
Вот одноклассник дзинчжу, которого мы использовали в проекте.gormв виде библиотеки форм. Если вы используете другие orm-библиотеки golang, реализация должна быть аналогичной.
Наша задача определяется из этой структуры модели ниже:
Сгенерируйте оператор построения таблицы mysql (файл):
идеи
отmodel struct
генерироватьsql
Является将语言A翻译为语言B
Проблема. Этот процесс в принципе ничем не отличается от компиляции исходного кода в бинарную исполняемую программу. Таким образом, эта проблема по существу является проблемой компиляции. Полная компиляция состоит из следующих шагов:
Для задач, которые необходимо выполнить в этой статье, в основном выполните лексический анализ, синтаксический анализ и генерацию целевого кода.
инструмент
Для лексического анализа и синтаксического анализа у нас есть древний артефактLexа такжеYacc, Yet Another Compiler-Compiler... И мы просто хотим выполнить задачу по созданию файла таблицы. Иногда пользователям приходится настраивать синтаксис двух инструментов, и им приходится писать свои собственные файлы lex и yacc. Мне это не нравится...
В Golang есть много инструментов, которым завидуют другие языки, например go pprof, go list, go vet и т. д. С точки зрения языкового метапрограммирования, в go 1.4 реализована начальная загрузка; лексический анализ и синтаксический анализ, используемые при компиляции, уже давно помещены в стандартную библиотеку.go/ast
середина.AST
Это аббревиатура от абстрактного синтаксического дерева, а дословный перевод — абстрактное синтаксическое дерево. С помощью AST мы можем написать программу для разбора исходного кода go. В зависимости от задачи, которую необходимо выполнить в этой статье, нам нужно написать программу, подобную этой, для анализа модели, определяющей таблицу данных.
struct, а затем сгенерируйте оператор построения таблицы sql.
выполнить
Применительно к реализации нашей задачи ее можно разделить на следующие этапы:
- Загрузить исходный код, сгенерировать дерево AST
- Получить и проанализировать структуру модели AST
- Создать create_definition, table_options на основе имени/тега поля структуры
Полная реализация кода, вы можете перейти на githubgorm2sql.
Осознайте эффект:
user_email.go
:
type UserBase struct {
UserId string `sql:"index:idx_ub"`
Ip string `sql:"unique_index:uniq_ip"`
}
type UserEmail struct {
Id int64 `gorm:"primary_key"`
UserBase
Email string
Sex bool
Age int
Score float64
UpdateTime time.Time `sql:"default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"`
CreateTime time.Time `sql:"default:CURRENT_TIMESTAMP"`
}
gorm2sql sql -f user_email.go -s UserEmail -o db.sql
Result:
CREATE TABLE `user_email`
(
`id` bigint AUTO_INCREMENT NOT NULL ,
`user_id` varchar(128) NOT NULL ,
`ip` varchar(128) NOT NULL ,
`email` varchar(128) NOT NULL ,
`sex` boolean NOT NULL ,
`age` int NOT NULL ,
`score` double NOT NULL ,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_ub (`user_id`),
UNIQUE INDEX uniq_ip (`ip`),
PRIMARY KEY (`id`)
) engine=innodb DEFAULT charset=utf8mb4;