Procházet zdrojové kódy

SVI Добавление примера

SVI před 2 roky
rodič
revize
3166f85711
1 změnil soubory, kde provedl 59 přidání a 20 odebrání
  1. 59 20
      docs/lesson01.md

+ 59 - 20
docs/lesson01.md

@@ -66,32 +66,71 @@ func FindRecord(ctxApp app.AppContext, numRecord string) error {
 ### Дочерний контекст с таймаутом внешнего ресурса
 
 ```go
-func Index(ctx contextContext, request *IndexRequest)(*IndexResponse, error){
-    chErr := make (chan error, 2)
-    ctxTimeout, fnCancel := cntext.WithTimeout(ctx, time.Millisecond * 500)
+
+// LocalStorage -- локальное хранилище ключ-значение
+type LocalStorage interface {
+    // Получить значение п оключу
+    Get(string) (*IndexResponse, error)
+}
+
+// IndexRequest -- запрос индексной страницы
+type IndexRequest struct {
+    Name string // Имя на индексной странице
+}
+
+// IndexResponse -- ответ на запрос инжексной страницы
+type IndexResponse struct {
+  // Определение полей структуры IndexResponse
+}
+
+var (
+  db LocalStorage // Объект локального хранилища
+)
+
+// Index -- запрос индексной страницы
+func Index(ctx context.Context, request *IndexRequest) (*IndexResponse, error) {
+
+    // Дочерний контекст и ег офункция отмены
+    ctxTimeout, fnCancel := context.WithTimeout(ctx, time.Millisecond*500)
+    // Обязательный вызов отмены контекста при выходе, иначе будет утечка памяти!!
     defer fnCancel()
-    var (
-        resp = &IndexResponse{}
-        err error
-    )
-    fnWork := func(){
-        defer close(chError)
+
+    type Resp struct {
+        resp *IndexResponse // Полезный ответ (если нет ошибки)
+        err error           // Ошибка (если была)
+    }
+
+    chResp := make(chan *Resp, 1) // Канал для получения результата после обработки
+
+    // Эта функция должна работат ьв отдельном потоке. Иначе невозможно
+    // устроить соревнование между глобальным контекстом и дочерним.
+    fnWork := func() {
+        defer close(chResp) // Обязательн озакрыт ьканал при выходе
         resp, err = db.Get(request.Name)
-        if err!=nil{
-            chErr <- err
+        if err != nil { // Была ошибка -- вернём только ошибку
+            resp := &Resp {
+                err: err,
+            }
+            chResp <- resp
             return
-        }
     }
-    go fnWork()
-    select {
-        case <-ctxTimeout.Done(): // Был ли таймаут?
+    resp := &Resp { // Ошибки не было -- значит вернём только результат.
+        err: err,
+    }
+    chResp <- resp
+  }
+
+    go fnWork() // Обязательно! Запуск в отдельном потоке
+
+    select { // Здесь гонки между таймаутом и полезным результатом -- кто быстрее.
+        case <-ctxTimeout.Done(): // Был ли таймаут дочернего контекста?
             return nil, fmt.Errorf("Index(): timeout in make response")
-        case err<-chErr: // Была ли ошибка?
-            if err!=nil{
-                eturn nil, fmt.Errorf("Index(): in make response, err=\n\t%w", err)
+        case result := <-chResp: // Что там с результатом?
+            if result.err != nil {
+                return nil, fmt.Errorf("Index(): in make response, err=\n\t%w", result.err)
             }
+            // Всё ок, возвращаем полезный результат
+            return result.resp, nil
     }
-    return resp, nil
 }
-
 ```