FlutterGO: мастер-класс по Fullstack.

Начните работать с двумя наиболее популярными технологиями Google!

Если вы читаете это, значит, вам либо слишком скучно и нечем заняться, либо вам просто надоели все хипстерские штучки, которые вы изучали раньше, и теперь вы хотите поднять уровень своей игры в программную инженерию и изучить либо Flutter, либо GO, а может быть, и то, и другое. Как бы там ни было, я вас понял.

Что такое Flutter?

Flutter, разработанный техническими мастерами Google, представляет собой набор средств разработки пользовательского интерфейса (SDK) с открытым исходным кодом, позволяющий создавать нативно скомпилированные приложения для нескольких платформ на основе единой кодовой базы. Это означает, что вы можете создавать потрясающие приложения для iOS, Android, веб и даже настольных компьютеров на основе единой кодовой базы – вот что значит эффективность!

Что такое GO?

Язык Go, также известный как Golang, был создан группой блестящих инженеров компании Google. Это язык программирования с открытым исходным кодом, который сочетает в себе простоту разработки динамических языков, таких как Python, с производительностью и безопасностью статически-типизированных языков, таких как C++. Это уникальное сочетание делает Go фантастическим вариантом для создания надежного и масштабируемого программного обеспечения.

Итак… Что же такое FlutterGO?

Вы угадали! Flutter для клиентской части, GO для серверной!

Создание API в GO

Мы создадим API в GO с помощью gorilla mux. Не волнуйтесь, это всего лишь пакет, который поможет нам в создании API.

Перед написанием кода загрузите пакет Mux, перейдите в корень вашего проекта go и введите;

go get -u github.com/gorilla/mux

Или можно посетить страницу установки.

Начнем с операторов импорта.

import (
 "encoding/json"
 "fmt"
 "log"
 "net/http"

 "github.com/gorilla/mux"
)

Если вы не понимаете всех этих импортов, не беспокойтесь, они будут описаны в последующих разделах.

Структуры

Итак, мы создадим API, который сможет получать курсы, добавлять новые курсы, обновлять курсы и удалять их – в общем, старый добрый CRUD. Начнем со структур.

type Course struct {
 Name   string  `json:"name"`
 Price  int     `json:"price"`
 Id     string  `json:"id"`
 Author *Author `json:"author"`
}

type Author struct {
 Name   string `json:"name"`
 Github string `json:"github"`
}

// A fake database
var courseDB []Course

Пока мы не будем использовать базу данных, пример использования MongoDB Atlas с GO можно посмотреть по этой ссылке. В качестве источника данных будет выступать срез courseDB.

Для работы наших конечных точек API мы сделаем следующие методы.

func courses(w http.ResponseWriter, r *http.Request) {
 switch r.Method {
 case "GET":
  getCourses(w, r)
 default:
  http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
 }
}

func course(w http.ResponseWriter, r *http.Request) {
 switch r.Method {
 case "GET":
  getCourse(w, r)
 case "POST":
  addCourse(w, r)
 case "PUT":
  updateCourse(w, r)
 case "DELETE":
  deleteCourse(w, r)
 default:
  http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
 }
}

Писатель ответа, как следует из названия, используется для записи ответа, вы можете использовать функцию WriteHeader() для записи кода состояния в ответ. Request помогает нам обрабатывать запросы, подробнее об этом рассказано в первом примере.

Создание методов, использованных ранее

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

Получить все курсы

func getCourses(w http.ResponseWriter, r *http.Request) {
 if len(courseDB) == 0 {
  w.WriteHeader(http.StatusNotFound)
  return
 }
 w.Header().Set("Content-Type", "application/json")
 e := json.NewEncoder(w)
 e.Encode(courseDB)
}

Поиск конкретного курса

func getCourse(w http.ResponseWriter, r *http.Request) {
 w.Header().Set("Content-Type", "application/json")
 params := mux.Vars(r)
 e := json.NewEncoder(w)
 for _, c := range courseDB {
  if c.Id == params["id"] {
   e.Encode(c)
   return
  }
 }
 w.WriteHeader(http.StatusNotFound)
}

Добавление курса

func addCourse(w http.ResponseWriter, r *http.Request) {
 w.Header().Set("Content-Type", "application/json")
 e := json.NewEncoder(w)

 var c Course
 err := json.NewDecoder(r.Body).Decode(&c)
 if err != nil {
  w.WriteHeader(http.StatusBadRequest)
  return
 }
 if c.IsEmpty() {
  w.WriteHeader(http.StatusBadRequest)
  return
 }
 courseDB = append(courseDB, c)
 w.WriteHeader(http.StatusCreated)
 e.Encode(c)
}

Обновление курса

func updateCourse(w http.ResponseWriter, r *http.Request) {
 w.Header().Set("Content-Type", "application/json")
 e := json.NewEncoder(w)

 var crs Course
 err := json.NewDecoder(r.Body).Decode(&crs)
 if err != nil {
  w.WriteHeader(http.StatusBadRequest)
  return
 }
 if crs.IsEmpty() {
  w.WriteHeader(http.StatusBadRequest)
  return
 }
 params := mux.Vars(r)
 for i, c := range courseDB {
  if c.Id == params["id"] {
   courseDB = append(courseDB[:i], courseDB[i+1:]...)
   courseDB = append(courseDB, crs)
   w.WriteHeader(http.StatusCreated)
   e.Encode(crs)
   return
  }
 }
 w.WriteHeader(http.StatusNotFound)
}

Удаление курса

func deleteCourse(w http.ResponseWriter, r *http.Request) {
 w.Header().Set("Content-Type", "application/json")
 params := mux.Vars(r)
 for i, c := range courseDB {
  if c.Id == params["id"] {
   courseDB = append(courseDB[:i], courseDB[i+1:]...)
   w.WriteHeader(http.StatusNoContent)
   return
  }
 }
 w.WriteHeader(http.StatusNotFound)
}

Это было очень много.
Мы можем получить полезную нагрузку с помощью mux.Vars(request), в настоящее время мы отправляем только “id” в полезной нагрузке.
Используя ResponseWriter, мы создадим наш кодировщик и закодируем ответ, который будет получен на стороне клиента.

Клиентская часть

Клиентская часть будет построена с использованием flutter. Я не буду вдаваться в детали фронтенда, уверен, что вы сможете разобраться с этим самостоятельно. Мы разберем, как использовать конечные точки API, которые мы создали во flutter.

Пакеты

Вы можете добавить свои любимые пакеты, которые я буду использовать для работы с конечными точками API. Вы можете посмотреть страницу pub dev здесь.
Вместо того чтобы читать всю документацию, перейдите в корень вашего проекта flutter и просто выполните команду;

flutter pub add http

После добавления пакета мы можем получить данные в формате json следующим образом.

Выборка всех курсов

 static Future<List<Map<String, dynamic>>> fetchAllCourses() async {
    const url = 'http://localhost:8080/courses';
    try {
      final raw = await _client.get(Uri.parse(url));
      final response = jsonDecode(raw.body);
      List<Map<String, dynamic>> data = [];
      for (var item in response) {
        data.add(item as Map<String, dynamic>);
      }
      return data;
    } catch (e) {
      debugPrint("Error: $e");
      throw Exception('Failed to load courses.');
    }
  }

Получение конкретного курса

static Future<Map<String, dynamic>> fetchCourseById(String id) async {
    final url = 'http:localhost:8080/courses/$id';
    try {
      final response = await http.get(Uri.parse(url));
      return response.body as Map<String, dynamic>;
    } catch (e) {
      debugPrint("Error: $e");
      throw Exception('Failed to load courses.');
    }
  }

Добавление курса

static Future<void> addCourse(Map<String, dynamic> course) async {
    const url = 'http:localhost:8080/courses';
    try {
      final response = await http.post(Uri.parse(url), body: course);
      if (response.statusCode != 200) {
        throw Exception('Failed to add course.');
      }
    } catch (e) {
      debugPrint("Error: $e");
      throw Exception('Failed to add courses.');
    }
  }

Обновление курса

 static Future<void> updateCourse(Map<String, dynamic> course) async {
    final url = 'http:localhost:8080/courses/${course['id']}';
    try {
      final response = await http.put(Uri.parse(url), body: course);
      if (response.statusCode != 200) {
        throw Exception('Failed to update course.');
      }
    } catch (e) {
      debugPrint("Error: $e");
      throw Exception('Failed to update courses.');
    }
  }

Удаление курса

static Future<void> deleteCourse(String id) async {
    final url = 'http:localhost:8080/courses/$id';
    try {
      final response = await http.delete(Uri.parse(url));
      if (response.statusCode != 200) {
        throw Exception('Failed to delete course.');
      }
    } catch (e) {
      debugPrint("Error: $e");
      throw Exception('Failed to delete courses.');
    }
  }

Обращаясь к созданным ранее конечным точкам, мы можем добиться желаемых действий! Эти специфические ответы могут быть использованы в пользовательском интерфейсе!

Как протестировать API?

Создавать весь фронтенд перед тестированием API – довольно глупое решение. Для этого можно использовать либо “Postman”, либо “Thunder Client”, оба из которых доступны в качестве расширений для VS Code.

FlutterGO: мастер-класс по Fullstack.
Вот как можно протестировать API с помощью Postman

Заключение

Flutter и GO – это мощные технологии, которые помогут вам повысить уровень своей игры в области разработки программного обеспечения.
Для просмотра всего исходного кода можно обратиться к этому репозиторию.

+1
0
+1
0
+1
0
+1
0
+1
1

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *