Initial commit
This commit is contained in:
112
README.md
Normal file
112
README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Notes App — Flutter + Go + gRPC (Protobuf)
|
||||
|
||||
Fullstack приложение-пример: **единая типизация** между Flutter фронтендом и Go бекендом через Protocol Buffers.
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
.
|
||||
├── proto/ # ЕДИНЫЙ ИСТОЧНИК ПРАВДЫ
|
||||
│ ├── notes/v1/notes.proto # Типы + API контракт
|
||||
│ ├── buf.yaml # Конфиг Buf (линтинг, deps)
|
||||
│ └── buf.gen.yaml # Конфиг кодогенерации
|
||||
│
|
||||
├── backend/ # Go gRPC сервер
|
||||
│ ├── main.go # Точка входа, запуск gRPC
|
||||
│ ├── service/note_service.go # Реализация NoteService
|
||||
│ └── gen/notes/v1/ # Сгенерированный Go код
|
||||
│ ├── notes.pb.go # Структуры (Note, Request, Response)
|
||||
│ └── notes_grpc.pb.go # gRPC интерфейсы и регистрация
|
||||
│
|
||||
├── frontend/ # Flutter приложение
|
||||
│ └── lib/
|
||||
│ ├── main.dart # Точка входа
|
||||
│ ├── screens/notes_screen.dart
|
||||
│ ├── services/grpc_client.dart
|
||||
│ └── gen/notes/v1/ # Сгенерированный Dart код
|
||||
│ ├── notes.pb.dart # Классы (Note, Request, Response)
|
||||
│ └── notes.pbgrpc.dart # gRPC клиент NoteServiceClient
|
||||
│
|
||||
└── generate.sh # Скрипт кодогенерации
|
||||
```
|
||||
|
||||
## Как это работает
|
||||
|
||||
```
|
||||
notes.proto (единый контракт)
|
||||
│
|
||||
buf generate
|
||||
┌─┴─┐
|
||||
│ │
|
||||
Go structs Dart classes
|
||||
+ gRPC server + gRPC client
|
||||
│ │
|
||||
backend/gen frontend/lib/gen
|
||||
```
|
||||
|
||||
1. Все типы и API описаны в одном `.proto` файле
|
||||
2. Из него генерируется типизированный код для **обоих** языков
|
||||
3. Изменил proto → перегенерировал → **ошибки компиляции** на той стороне, где контракт нарушен
|
||||
4. Невозможно отправить запрос с неверным типом — Dart не скомпилируется
|
||||
5. Невозможно вернуть ответ с неверной структурой — Go не скомпилируется
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### 1. Запуск Go бекенда
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
go run main.go
|
||||
# → gRPC server listening on :50051
|
||||
```
|
||||
|
||||
### 2. Запуск Flutter фронтенда
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
flutter run -d windows # или -d chrome, -d android и т.д.
|
||||
```
|
||||
|
||||
### 3. Перегенерация кода (после изменения proto)
|
||||
|
||||
```bash
|
||||
# Установи buf (один раз):
|
||||
npm install -g @bufbuild/buf
|
||||
|
||||
# Генерация:
|
||||
bash generate.sh
|
||||
```
|
||||
|
||||
Или через protoc напрямую:
|
||||
```bash
|
||||
# Установи плагины (один раз):
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
dart pub global activate protoc_plugin
|
||||
|
||||
# Генерация:
|
||||
bash generate.sh
|
||||
```
|
||||
|
||||
## Ключевая идея
|
||||
|
||||
Представь, что ты добавил новое поле `priority` в заметку:
|
||||
|
||||
```protobuf
|
||||
message Note {
|
||||
string id = 1;
|
||||
string title = 2;
|
||||
string content = 3;
|
||||
google.protobuf.Timestamp created_at = 4;
|
||||
google.protobuf.Timestamp updated_at = 5;
|
||||
int32 priority = 6; // ← НОВОЕ ПОЛЕ
|
||||
}
|
||||
```
|
||||
|
||||
После `buf generate`:
|
||||
- В Go: `note.Priority` доступно сразу
|
||||
- В Dart: `note.priority` доступно сразу
|
||||
- Оба языка знают о новом поле на этапе **компиляции**
|
||||
- Если забыл его обработать — компилятор предупредит
|
||||
|
||||
Это аналог того, что Next.js делает для TS фронта/бека, но для **разных языков**.
|
||||
Reference in New Issue
Block a user