剛開始編程時,發現寫遞歸函數仍是有點難,搞很差就形成程序意外退出、卡死等尷尬處境。其實寫好遞歸函數只要把握2點,就能夠作到媽媽不再用擔憂個人遞歸了。web
一、遞歸函數中要有調用本身的地方(也就是說有繼續遞歸的條件和遞歸處理)編程
二、遞歸函數中要有結束本身的地方(也就是說有遞歸結束的條件和結束處理)函數
打印指定目錄的文件結構(即有子目錄,也要打印子目錄下的文件)spa
打印的目錄格式以下:code
--- home ------ MS --------- Version ------------ S900 --------------- odbg.jpg ------------ S910 --------------- myweb.jpg ------ VER --------- hello.txt
Go語言代碼以下:遞歸
package main import ( "fmt" "io/ioutil" "os" ) func main() { var path string path = "G:\\home" err := PrintFilesInDir(path, "") if err != nil { fmt.Println("PrintFilesInDir:: err=", err.Error()) } } func PrintFilesInDir(dirPath string, preSpace string) error { //文件名前面空格,便於標識文件層次 preSpace = fmt.Sprintf("%s---", preSpace) //獲取文件信息 finf, err := os.Stat(dirPath) if err != nil { fmt.Println("PrintFilesInDir:: os.Stat err=", err.Error()) return err } if finf.IsDir() { //若是是目錄須要遞歸子文件 //打印目錄名 fmt.Println(preSpace, "", finf.Name()) //獲取此目錄子文件名 finfs, err := ioutil.ReadDir(dirPath) if err != nil { fmt.Println("PrintFilesInDir:: ioutil.ReadDir err=", err.Error()) return err } for _, v := range finfs { sonDir := fmt.Sprintf("%s\\%s", dirPath, v.Name()) PrintFilesInDir(sonDir, preSpace) } } else { //若是不是目錄,打印出此文件名,結束遞歸 fmt.Println(preSpace, "", finf.Name()) return nil } return nil }
到此爲止,主要內容就已經說完了,下面就是一些關於遞歸的討論了......string
(1)能夠減小代碼量。幾行問題能夠解決的不必使用幾十行來寫
(2)處理邏輯清晰,便於理解io
(1) 子問題須與原始問題爲一樣的事,且更爲簡單;class
(2)不能無限制地調用自己,須有個出口,化簡爲非遞歸情況處理。效率
其實就是一個問題中的一樣的處理邏輯須要作不少次,並且處理邏輯中也有結束的處理。
運行效率較低、 在遞歸調用的過程中系統爲每一層的返回點、局部量等開闢了棧來存儲。遞歸次數過多容易形成棧溢出等
本文主要給你們介紹,怎麼去寫遞歸,不會形成程序異常(只要把握住繼續遞歸和結束遞歸條件這兩點就OK啦)。