Функция filepath.Walk
выполняет функцию обратного вызова функции. Это прямая функция без указателя контекста. Разумеется, основным вариантом использования Walk
является прохождение каталога и принятие на нем определенных действий со ссылкой на более широкий контекст (например, ввод каждого файла в таблицу).
Если бы я писал это на С#, я бы использовал объект (с полями, которые могли бы указывать на объекты в контексте) в качестве обратного вызова (с заданным методом обратного вызова), чтобы объект мог инкапсулировать контекст, который Walk
вызывается из.
(EDIT: пользователь usr" предполагает, что метод закрытия также встречается на С#)
Если бы я писал это на C, я бы попросил функцию и указатель контекста как void *
, чтобы функция имела указатель контекста, который она может передать в функцию Walk
, и передать ее в функция обратного вызова.
Но Go имеет только аргумент функции и не имеет очевидного аргумента указателя контекста.
(Если бы я разработал эту функцию, я бы взял объект как обратный вызов, а не функцию, соответствующую интерфейсу FileWalkerCallback
или тому подобное, и поместил на этот интерфейс метод callback(...)
. Тогда потребитель мог бы присоедините любой контекст к объекту, прежде чем передавать его на Walk
.)
Единственный способ, которым я могу это сделать, - захватить закрытие внешней функции в функции обратного вызова. Вот как я его использую:
func ScanAllFiles(location string, myStorageThing *StorageThing) (err error) {
numScanned = 0
// Wrap this up in this function closure to capture the `corpus` binding.
var scan = func(path string, fileInfo os.FileInfo, inpErr error) (err error) {
numScanned ++
myStorageThing.DoSomething(path)
}
fmt.Println("Scan All")
err = filepath.Walk(location, scan)
fmt.Println("Total scanned", numScanned)
return
}
В этом примере я создаю функцию обратного вызова, поэтому ее замыкание содержит переменные numScanned
и myStorageThing
.
Это кажется мне неправильным. Правильно ли я считаю, что это странно, или я просто привык писать "Go"? Как он предназначен для метода filepath.Walk
для использования таким образом, чтобы обратный вызов ссылался на более широкий контекст?