I’m new to Go and started to learn it yesterday. I have some programming experience so it was pretty easy to pick up. Everything was pretty good until I’ve hit this wall.
Basically, I’m doing a little program for fun (and for learning) that loops through files using filepath.Walk and I want it to append the files to fileList only if they have a specific extension.
var fileList []string
var extensions = []string{".exe", ".dll", ".sys"}
filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if filepath.Ext(path) := range extensions {
fileList = append(fileList, path)
}
}
return nil
The issue I encounter is when it reaches if filepath.Ext(path) := range extensions, this part doesn’t work. But it I do if filepath.Ext(path) == ".exe" || filepath.Ext(path) == ".dll" || filepath.Ext(path) == ".sys" it works fine. But I don’t think it looks nice and if there is something I don’t understand dealing with arrays and slices, I need to know what it is.
By the way I also have no idea of how filepath.Walk() works, took a snippet from a site so if someone wants to explain I’d appreciate it too. Seems similar to os.walk() in Python but clearly isn’t working the same way.
Go doesn’t have a builtin for checking if an element is in a list, like the in operator in Python. Instead, you do it manually by looping over it, or you use a map, or you use a sorted slice and sort.Search.
func stringInSlice(v string, ss []string) bool {
for _, s := range ss {
if s == v {
return true
}
}
return false
}
exts := []string{".exe", ".dll", ".sys"}
if stringInSlice(filepath.Ext(path), exts) {
// it's an executable
}
exts := map[string]bool {
".exe": true,
".dll": true,
".sys": true,
}
if exts[filepath.Ext(path)] {
// it's an executable
}
(People will quibble you should use a map[string]struct{} instead. Ignore them until you understand what that is and why it might be better.)
func stringInSortedSlice(v string, ss []string) bool {
i := sort.Search(len(ss), func(i int) bool { return ss[i] >= v })
return i < len(ss) && ss[i] == v
}
exts := []string{".dll", ".exe", ".sys"} // n.b. sorted
if stringInSortedSlice(filepath.Ext(path), exts) {
// it's an executable
}
filepath.Walk will call the function you give it, for every path it finds.
Makes more sense now. I was struggling to understand why none of my attempts were working. I’ll try that out!
As for map[string]struct{} you’re right that doesn’t mean anything to me for the moment but I found this blog post about it: https://blog.golang.org/go-maps-in-action so I’ll give it a read later.