Вот пример, который показывает вам, как создать настольное приложение для ввода данных, способное выполнять операции CRUD, используя язык Go, набор инструментов Fyne GUI и сервер базы данных MongoDB.

В этой статье я покажу вам, как создать небольшое настольное приложение, в котором вы можете вводить, просматривать, обновлять и удалять контактную информацию. Я буду программировать это приложение на языке Go (Golang) и использовать набор инструментов Fyne GUI для создания пользовательского интерфейса. Контактная информация будет храниться в базе данных MongoDB.

Кроме того, эта статья является продолжением моих предыдущих статей о Fyne и MongoDB. Вы увидите концепции, описанные в этих статьях, и некоторые новые идеи. Если вы испытываете трудности с пониманием концепций этой статьи, вы можете сначала прочитать предыдущие.

Эти статьи являются результатом моих выводов, основанных на моих исследованиях языка Go.

Предварительные требования

Убедитесь, что вы установили пакет Fyne и драйверы MongoDB для Go. Чтобы создавать программы Go, использующие Fyne, вам также необходимо установить GCC. Кроме того, вам необходимо установить сервер MongoDB.

Я также счел полезным установить приложение MongoDB Compass для устранения неполадок.

Основная структура

Нам понадобится структура данных для представления контактов, которые мы хотим сохранить в нашем настольном приложении.

По сути это обычная структура, но с добавленными аннотациями для BSON. BSON — это двоичная версия JSON, используемая MongoDB. Подробнее об использовании структур с аннотациями BSON читайте здесь.

В строке 2 мы создаем определенное свойство с именем ID, которое будет содержать уникальный идентификатор _id, предоставленный MongoDB, когда мы создаем и вставляем документ в коллекцию. Поэтому мы добавили этот ключ в аннотацию BSON. Мы также предоставили свойству ID тип primitive.ObjectID. Это особый тип, определенный для идентификаторов MongoDB.

Подробнее об использовании BSON читайте здесь.

Функции CRUD

Учитывая, что по крайней мере одну из функций CRUD необходимо вызывать несколько раз, я решил реализовать их в отдельных функциях вне функции main() программы. Кроме того, это облегчит реструктуризацию программы в будущем.

Во-первых, мы «упаковываем» контекст и коллекцию контактов MongoDB в одну структуру данных с именем ContactCollection. Эту структуру можно легко создать с помощью конструктора NewContactCollection().

Затем мы реализуем 4 функции CRUD:

  • Создание реализовано CreateContact()
  • Чтение реализовано GetAll()
  • Обновление реализовано UpdateContact()
  • Удаление осуществляется DeleteContact()

Эти функции используют коллекцию контекста и контактов, поэтому мы упаковали их в структуру.

Создание графического интерфейса Fyne

Ниже вы можете найти скелет функции main().

Некоторые части были опущены в приведенном выше фрагменте кода; вы можете найти их под другими подзаголовками ниже.

По сути, приведенный выше код создает окно Fyne размером 1000 пикселей в ширину и 600 пикселей в высоту в центре экрана. Это окно установлено в качестве главного окна. Это означает, что все другие окна также будут закрыты, когда будет закрыто это окно. В данном примере это, по сути, менее важно, так как других окон нет.

Кроме того, содержимое окна устанавливается в соответствии с различными функциями макета. Ниже вы можете найти скриншот того, как будет выглядеть результирующее окно.

Обратите внимание, что на скриншоте выше добавлено два контакта.

Настройка клиента MongoDB, коллекции и получение всех документов.

В строках 3–9 мы создаем базовый контекст с помощью context.TODO() и подключаемся к серверу MongoDB, работающему на localhost:27017.

В строках 10–12 мы пингуем сервер базы данных, чтобы убедиться, что мы установили соединение.

В строке 13 отложено отключение от базы данных. Это означает, что оператор разъединения будет выполняться после всех остальных операторов функции main().

В строке 17 мы подключаемся к коллекции contacts в базе данных contactdb. Если их нет, то они будут созданы.

В строке 18 создается структура ContactCollection с помощью функции с именем NewContactCollection(). Эта структура с именем cc будет содержать контекст и ссылку на коллекцию, как описано в предыдущем заголовке.

В строке 20 мы используем функцию GetAll() для получения всех контактов из коллекции базы данных. Эти контакты сохраняются в срезе под названием loadedData, определенном в строке 1.

Реализация виджета списка

В приведенном выше фрагменте кода виджет list создается с помощью функции NewList(). Если вы не знакомы с виджетом list от Fyne, вы можете быстро просмотреть документацию.

В строке 2 мы передаем первый аргумент функции. Этот аргумент является длиной слайса loadedData. По сути, это количество контактов в базе данных.

В строках 3–13 мы создаем макет каждой строки в виджете list. Такая строка содержит следующие графические элементы (виджеты):

  • Ярлык для имени определенного контакта
  • Метка для фамилии определенного контакта
  • Ярлык для адреса электронной почты определенного контакта.
  • Ярлык для номера телефона определенного контакта.
  • кнопкадляредактирования определенного контакта.
  • кнопкадляудаления определенного контакта

Эти элементы добавляются к CanvasObject с помощью NewHBox(), NewGridWithColumns() и NewBorder() в зависимости от того, где мы хотим их расположить. Подробнее о макетах здесь.

В строках 14–105 данные из среза loadedData извлекаются для заданного контакта (на основе ListItemID) и вводятся в графические элементы, настроенные в предыдущих строках.

В строках 17–26 фактические графические элементы извлекаются из файла CanvasObject.

В строке 28 получаем ID текущего контакта.

В строках 30–33 задаются текстовые свойства меток с данными от текущего контакта.

В строках 35–78 реализуем функционал кнопки редактирования. Когда кнопка редактирования нажата (или «нажата»), открывается диалоговое окно. Это диалоговое окно содержит форму, в которой поля заполнены существующими данными контакта.

Когда вы нажимаете кнопку «Сохранить» в диалоговом окне, новые данные сохраняются в структуру Contact с именем contact. contact отправляется функции UpdateContact(), которая обеспечивает обновление базы данных.

После этого loadedData обновляется с помощью GetAll() и обновляется виджет list.

Ниже вы можете увидеть скриншот диалогового окна в действии.

В строках 80–103 реализуем функционал кнопки удаления. При нажатии кнопки удаления открывается диалоговое окно. Это диалоговое окно содержит вопрос «Вы хотите удалить этот контакт?».

Теперь вы можете нажать «Да» или «Нет». Если вы нажмете «Да», текущий контакт будет удален. contactID отправляется функции DeleteContact(), которая удаляет контакт из базы данных.

Наконец, loadedData обновляется с помощью GetAll(), а виджет list обновляется.

Ниже вы можете увидеть скриншот диалогового окна удаления в действии.

Реализация кнопки «Добавить контакт»

Функционал кнопки «Добавить контакт» практически аналогичен кнопке «Изменить».

Когда мы нажимаем кнопку «Добавить контакт», открывается диалоговое окно. Это диалоговое окно содержит форму с пустыми полями для четырех свойств контакта.

При нажатии кнопки «Добавить» в диалоговом окне новые данные сохраняются в структуру Contact с именем c. Контакт отправляется в функцию CreateContact(), которая следит за тем, чтобы контакт c был добавлен в базу данных.

Опять же, loadedData обновляется с помощью GetAll(), а виджет list обновляется.

Ниже вы можете увидеть скриншот этого диалогового окна.

Полный код

Комментарии и дальнейшая работа

В этом примере весь код помещен в один файл. Это не рекомендуемая практика кодирования для производственного кода.

Функции CRUD могут быть реализованы для разных серверов баз данных и файлов JSON или YAML.

Код из этой статьи мог бы стать основой CRM-системы.

Рекомендации