Go: Отложенные функции

В Go есть полезная конструкция defer, которая позволяет выполнять функции в фазе выхода из текущей функции. Например:

package main

import (
	"fmt"
)

func main() {
	// функция выполнится в самом конце при выходе из main
	defer fmt.Println("finish")

	fmt.Println("start")
}

Вывод:

start
finish

Такие функции называются отложенными. Каждая такая функция добавляется в стек отложенных функций и будет выполнена в порядке LIFO (Last In First Out):

package main

import (
	"fmt"
)

func main() {
	defer fmt.Println("3rd")
	defer fmt.Println("2nd")

	fmt.Println("1st")
}

Вывод:

1st
2nd
3rd

Использование отложенных функций достаточно распространено. Например:

  • закрытие дескриптора файла после работы
  • возвращение соединения с базой данных в общий пул после чтения всех строк
  • закрытие TCP соединения после полного прочтения тела ответа

Задание

Реализуйте функцию ExecuteMergeDictsJob(job *MergeDictsJob) (*MergeDictsJob, error), которая выполняет джобу MergeDictsJob и возвращает ее. Алгоритм обработки джобы следующий:

  • перебрать по порядку все словари job.Dicts и записать каждое ключ-значение в результирующую мапу job.Merged
  • если в структуре job.Dicts меньше 2-х словарей, возвращается ошибка errNotEnoughDicts = errors.New("at least 2 dictionaries are required")
  • если в структуре job.Dicts встречается словарь в виде нулевого значения nil, то возвращается ошибка errNilDict = errors.New("nil dictionary")
  • независимо от успешного выполнения или ошибки в возвращаемой структуре MergeDictsJob поле IsFinished должно быть заполнено как true

Пример работы:

ExecuteMergeDictsJob(&MergeDictsJob{}) // &MergeDictsJob{IsFinished: true}, "at least 2 dictionaries are required"
ExecuteMergeDictsJob(&MergeDictsJob{Dicts: []map[string]string{{"a": "b"},nil}}) // &MergeDictsJob{IsFinished: true, Dicts: []map[string]string{{"a": "b"},nil}}, "nil dictionary"
ExecuteMergeDictsJob(&MergeDictsJob{Dicts: []map[string]string{{"a": "b"},{"b": "c"}}}) // &MergeDictsJob{IsFinished: true, Dicts: []map[string]string{{"a": "b", "b": "c"}}}, nil
Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

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

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются
Loading...

Ваше упражнение проверяется по этим тестам

1package solution
2
3import (
4	"github.com/stretchr/testify/assert"
5	"testing"
6)
7
8func TestExecuteMergeDictsJob(t *testing.T) {
9	a := assert.New(t)
10
11	job, err := ExecuteMergeDictsJob(&MergeDictsJob{})
12	a.Equal(errNotEnoughDicts, err)
13	a.Equal(true, job.IsFinished)
14
15	job, err = ExecuteMergeDictsJob(&MergeDictsJob{Dicts: []map[string]string{
16		{"a": "b"},
17	}})
18	a.Equal(errNotEnoughDicts, err)
19	a.Equal(true, job.IsFinished)
20
21	job, err = ExecuteMergeDictsJob(&MergeDictsJob{Dicts: []map[string]string{
22		{"a": "b"},
23		nil,
24	}})
25	a.Equal(errNilDict, err)
26	a.Equal(true, job.IsFinished)
27
28	job, err = ExecuteMergeDictsJob(&MergeDictsJob{Dicts: []map[string]string{
29		{"a": "b", "b": "c"},
30		{"d": "e", "f": "g"},
31		{"a": "z", "f": "g"},
32	}})
33	a.NoError(err)
34	a.Equal(true, job.IsFinished)
35	a.Equal(map[string]string{
36		"b": "c",
37		"d": "e",
38		"a": "z",
39		"f": "g",
40	}, job.Merged)
41}
42

Решение учителя откроется через:

20:00
waiting_clock