Не знам за вас, но когато започнах да програмирам терминът Рекурсия ме накара малко да потреперя. Мисля, че това е естествен отговор, честно казано. Новите неща могат да бъдат страшни! Също така не разбрах важността или потенциалното въздействие, което може да има използването на рекурсия във вашия код. Ако нямате солидна представа за рекурсията, имате късмет! Ще обсъдя как можете да впрегнете силата на рекурсията и да я използвате във вашите Go програми.

И така, какво е рекурсия?

многократното прилагане на процедура или определение

Обичайна употреба на рекурсия в програмирането е извикването на функция вътре в същата функция. Нека ви покажа един пример:

main:

  • Вътре в func main ние декларираме променливата n и присвояваме n на върнатата стойност на функцията factorial
  • Функцията factorial има един аргумент, 4 от тип int
  • На следващия ред на изпълнение, използвайки пакета fmt, отпечатваме стойността на n

Кратка бележка: във всяка рекурсивна функция трябва да има „базов случай“.

Базовият случай най-често е оператор if, който, когато бъде оценен на „вярно“

ще спре извикването на функцията във функцията (спиране на рекурсията)

и ще позволи на програмата да се върне извън функцията

factorial:

  • Под функцията main декларираме функция с идентификатор factorial
  • Функцията factorial има един параметър, n от тип int
  • Функцията factorial връща стойност от тип int
  • В този пример нашият основен случай в factorial е оператор if, който проверява дали стойността на n е 0
  • Тъй като нашият аргумент n е 4, това се оценява на false и ние продължаваме към следващия ред на изпълнение
  • Следващият ни ред е return израз, който съдържа израза n * factorial(n-1) какво означава това?

- Следващият ни ред е return изявление, което съдържа израза n * factorial(n-1) какво означава това?

n * factorial(n-1):

  • в първата итерация стойността на n е 4, така че можем да напишем този израз така: 4 * factorial(4–1)
  • можем да направим изваждането за аргумента за factorial, когато го направим, изразът изглежда така: 4 * factorial(3)
  • сега знаем, че имаме стойността на 4; обаче извикваме factorial отново с аргумента 3
  • тъй като извикваме factorial, прескачаме до първия ред на изпълнение във функцията
  • знаем, че стойността на n сега е 3; следователно нашият основен случай все още се оценява на false
  • сега, когато стойността на n е 3, нашият израз return сега изглежда така: 4 * 3 * factorial(3–1)
  • опростен: 4 * 3 * factorial(2)
  • извикваме factorial отново, като аргументът е стойността 2 от тип int
  • нашият основен случай все още се оценява на false, защото 2 не е равно на 0
  • нашето return изявление сега изглежда по следния начин: 4 * 3 * 2 * factorial(2–1)
  • опростен: 4 * 3 * 2 * factorial(1)
  • извикваме factorial отново, като аргументът е стойността 1 от тип int
  • нашият основен случай все още се оценява на false, защото 1 не е равно на 0
  • нашето return изявление сега изглежда по следния начин: 4 * 3 * 2 * 1 * factorial(1–1)
  • опростен: 4 * 3 * 2 * 1 * factorial(0)
  • този път нашият основен случай все още се оценява на true, защото 0 е равно на 0
  • вътре в нашия основен случай връщаме стойността 1 от тип int
  • сега, след като нашата рекурсия е готова, окончателният ни израз return ще изглежда така: return 4 * 3 * 2 * 1, който се оценява на стойността 24 от тип int

main:

  • сега, когато цялото изпълнение е завършено, стойността на n се оценява на 24, тази стойност се отпечатва на следващия ред

В обобщение

Надявам се, че ви е харесало да научите за рекурсията. Въпреки че този пример не е прекалено сложен, надявам се, че можете да си тръгнете, след като прочетете тази публикация, с по-добро разбиране на принципите на Рекурсията и да ги приложите в работния си процес. Ще кажа, че трябва да има ниво на предпазливост, когато пишете рекурсивни функции. Ако вашият основен случай не е здрав, можете да се окажете в положение, в което функцията ви може непрекъснато да се самоизвиква и неизбежно да причини „препълване на стека“. Въпреки това, когато е направено правилно, Рекурсията ни позволява да пишем чист, СУХ и ефективен код.

Следващата седмица ще обсъждам указатели, JSON Marshalling и JSON Unmarshalling. Ще се видим тогава!