Join David Gassner for an in-depth discussion in this video Walking a directory tree, part of Up and Running with Go.
- Go is used by a lot of developers to create simple IT management processes that clean up directory structures on a file system. I'll show you one of the most critical tools for this purpose. A function named walk from a package named filepath that lets you walk a directory structure and work with each directory or file in that structure one at a time. I'll go to the import statement in this file, walkDirs.go and I'll add an import for path/filepath.
Now, in my main function, first I am going to create a string that refers to my current directory, and gives me the absolute location of this directory. This step really isn't necessary, but it's good to know about some of the functions that are available in the filepath package. I'll call filepath.Abs for absolute, and I'll pass in a single dot representing the current directory. Then, I'll output Processing path and then I'll pass in the root.
Now I'll test just that much and for the moment I won't need the os package, so I'll comment that out. Then, I'll go to my command prompt and I'll run the code. And, I see Processing path and my absolute directory. Your output will differ depending on where you've put your files. Now I'm ready for the next step. I want to walk the directory structure and I can do that with a single function call.
Again, the name of the function is walk and it's part of the filepath package. It's going to return an error object and I'll capture that here by saying err and then I'll assign it using filepath.Walk and then I'll pass in my root folder and then the name of a function that I'm going to need to create. I'll name it processPath. For each directory and each file in the directory structure, this function will be called for me.
It'll need to have a very specific signature and I'll show you that in a moment. But first, I'll complete the main function. I'll add some conditional code and I'll check whether the error object is nil, and if it isn't, I'll output the error object. This will be the last line of code that executes in the main function. Now I'm ready to create my processPath function. I'll do that down here. You can name this function anything you want.
I'm calling it processPath, but you could call it visitPath, or walkthisPath, or anything. But it needs these three arguments of these particular types. First you need a string. This will represent the current directory or file name. Next you'll receive an info object and it's an instance of a structure named fileInfo that's a member of the os package. And now, I need to uncomment that import for the os package up here. And finally, you'll receive an error object and I'll name it error.
Your processPath function also will return an error object, so I'll declare that right here and that's the complete function signature. If you want to remind yourself about the signature for this function, go to the filepath documentation at this url, then go to the index of functions and down here at the bottom, you'll see WalkFunc and this is the function that I'm creating. Again, it receives a string, a FileInfo object and an error and it returns an error.
Now, here's how I'll implement my function. First, I'll check the error object and I'll see if it's nil, and if it isn't, I'll just return it, and that will be the end of this function. Now, the rule is if you return a non-nil error object, that will stop the Walk function from continuing to walk the path, and your main function will immediately jump down here and will work with the error object. But if you get past that bit of code, you're ready to get some information about the path that you're working with.
I'll add another bit of conditional code, and I'll make sure that I'm not working with the root folder. And to do that, I'll ask whether the path has a value of simply dot. And now, I'm ready to deal with each individual directory of file. The info object has a method named IsDir. It returns a Boolean value, true or false. If it's true, you're working with the directory, and if it's false, you're working with the file. So, if I'm working with the directory, I'll just output some information to the console, like this: with fmt.Println, and then I'll pass in a label of Directory and then the path.
Then, I'll add an else clause here, and this will be for if it's a file, and I'll copy this bit of code, and I'll change the label to File. At the end of the code, I'll return nil. Remember that this function says it's going to return an error, so I need to return something, and that's my processing function. And again, it will be called for each and every directory and file in the directory structure. Now this directory structure has some files and directories in it.
There are two directories and one of them has a file named hello.txt and the other one has a sub-directory and it has a file called hello.txt. So, I'll go back to my console, and I'll run the code again. And there's the result. I see the four directories and the three files. The two files named hello.txt and the one file which is my source code file. So now, once you're in the process path function, you can do anything you need to do.
You can read and write files. You can delete files, or any other task you need to accomplish to clean up your directory structure. The walk function uses this recursive pattern and for the first time, we've seen the process of using a function as a type. As something that you can pass into another function as an object, so that it can then easily be called recursively. As you dig deeper into the Go programming language, you'll find that this sort of recursion is actually very common, and it makes what might be otherwise very complex tasks, very, very easy.
- Installing Go tools
- Creating and compiling a Go workspace
- Exploring variables, constants, and types
- Storing ordered and unordered values
- Grouping related values in structs
- Programming conditional logic and loops
- Defining and calling functions
- Handling errors
- Working with files
- Creating a simple HTTP server