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