- Разрабатываем облачное ПО на Go+PostgreSQL+ReactJS - Разрабатываем ПО контроллеров группы светильников на Go - Разрабатываем собственную MESH радио сеть для передачи данных в диапазоне 868 MHz - Делаем дизайн и производим собственное железо в Китае - Зарабатываем на аутсорсе, всё заработанное вкладываем в стартап Lighting Management System
Go - Компилируемый и межплатформенный x86, AMD64, ARM - Windows и Linux - Статическая типизация - Автоматическое управление памятью - Богатая стандартная библиотека - Простой язык - Принудительная обработка ошибок - Быстрая компиляция - Встроенный тулинг - Статические зависимости Отсутствие дженериков Отсутствие дженериков
или создавать свое? Beego или go-kit? - Как организовать AAA - Какой выбрать router? - Что передавать в контекстах запросов - Где начинаются и заканчиваются принципы 12 fapp - Какой логгер выбрать? - Стандартного типа error не достаточно - Вебсокеты - Graceful shutdown - Generics - И куча других вопросов
} var ( person Person arr []Person ) rows, err := db.Query("SELECT id, name, last_name FROM persons") defer rows.Close() for rows.Next() { err = rows.Scan(&person.ID, &person.Name, &person.LastName) if err != nil { // обработка ошибки при чтении данных в переменные } arr = append(arr, row) } err = rows.Err() if err != nil { // обработка ошибки которая возникла в результате итерации по записям }
обозначения значений по умолчанию - Поддержка миграций - JOIN-ы - Хуки перед CRUD операциями - Поддержка особенностей PG. Например ON CONFLICT при INSERT - Chaining: db.Where("name LIKE $1", “Rob %").Find(&persons, "id IN ($2)", []int{1, 2, 3}).Count(&count)
- Если нужно изменить только некоторые поля таблицы - Много разных способов добиться одинакового результата - Сложные SQL запросы сначала пишутся и отлаживаются в SQL Manager, потом приходится разбивать на цепочки функций gorm - Админы жалуются на «мусорность» генерируемых SQL запросов - Нагрузка на Garbage collector
не нужны - Не писать SQL для типовых CRUD операций - Минимизировать нагрузку на GC - Уметь возможность выборочно игнорировать поля в разных запросах без создания промежуточных структур - Регистрировать время получения первой записи от СУБД и длительность чтения всех записей - Для CRU* операций отправлять в базу данных запросы содержащие только требуемые поля - В журнале помечать запросы выполняющиеся в рамках одной транзакции
- Отрисовываем все Foreign Keys! - Группируем таблицы по функциональным группам (микросервисам) для наглядности - Генерируем SQL для создания таблиц и других объектов БД - Автоматически заполняем собственную таблицу с метаданными - Генерируем описание типов данных Go из метаданных таблиц
name varchar(32), last_name text not null, blob bytea, CONSTRAINT persons_pk PRIMARY KEY (id) comment on column persons.name is ‘Имя. Правила: maxlen:32, trim'; // domain.go type Person struct { ID int `json:”id”` Name string `json:”name” dbw:”maxlen:32,trim”` LastName string `json:”last_name”` Blob []byte `json:”blob” dbw:”nocache,blob”` } .. . type PersonBalance struct { ID int `json:”id” dbw:”noseq”` // не нашли sequence который имеет имя person_balances_seq Balance int `json:”balance”` } type PersonWallet struct { ID string `json:”id”` Name string `json:”name” dbw:”maxlen:20”` Reserved int `json:”reserved” dbw:”noins”` Available int `json:”available” dbw:”min:0”` }
- Говно и палки! - Сразу вкатываем в реальные проекты, что бы библиотека быстрее приобрела форму - Небольшие неудобства в использовании без ущерба производительности допустимо!