Go language is a powerful programming language, but you may encounter some problems when dealing with file operations. In particular, when Program A opens a file, Program B may try to archive or delete the file, which may cause Program A to error. PHP editor Xigua here gives some methods to help you prevent program B from operating the file currently opened by program A in the Go language to ensure the stable operation of the program. Here are some solutions:
Programming language: Use the latest version
I'm working on a program A that needs to archive log files into a directory, excluding log files opened by program B, which uses it for logging. Open files will be closed after a specific duration (e.g. 24 hours) and then available for archiving. Obviously, both programs run independently.
The current implementation does not check if the file is open in program B, and since I recently discovered that it is archiving open log files, I don't think it does that; basically, it copies the file to the archive and deletes it.
What is a reliable way to check if a file is currently open by another Go program before trying to archive it?
I've written the archiver, but I won't post it here because there is no code that is not relevant to the problem, so I will only add the code that performs the archiving and deletion.
I have tried using the Open and OpenFile functions without success.
func zipFile(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer func(file *os.File) { err = file.Close() if err != nil { fmt.Println(err) } }(file) fileInfo, err := file.Stat() if err != nil { return err } archiveFile, err := os.Create(fmt.Sprintf("%s.zip", filename)) if err != nil { return err } defer func(archiveFile *os.File) { err = archiveFile.Close() if err != nil { fmt.Println(err) } }(archiveFile) zipWriter := zip.NewWriter(archiveFile) if err != nil { return err } defer func(zipWriter *zip.Writer) { err = zipWriter.Close() if err != nil { fmt.Println(err) } }(zipWriter) writer, err := zipWriter.Create(fileInfo.Name()) if err != nil { return err } _, err = io.Copy(writer, file) if err != nil { return err } err = os.Remove(filename) if err != nil { return err } fmt.Println(fmt.Sprintf("file %s was zipped", fileInfo.Name())) return nil }
Regardless of the process, the problem of knowing whether a file is open by another process is very dependent on the underlying operating system. Therefore, there is no universal cross-platform way to answer this question. For *NIX systems (Unix, Linux, macOS), the best way to answer your question is to use the core util lsof
("List open files").
On macOS, it looks like this:
package main import ( "fmt" "os/exec" "strings" ) func main() { out, _ := exec.Command("lsof").Output() for _, line := range strings.Split(string(out), "\n") { // Skip anything that's not a regular file if !strings.Contains(line, "REG") { continue } fields := strings.Fields(line) // The macOS lsof command has the filename in the ninth field fmt.Println(fields[8]) } }
Alternatively, you can find a library that abstracts this, like: https://github.com/wheel-complex/lsof
More information about lsof
: https://www.php.cn/link/fa2246fa0fdf0d3e270c86767b77ba1b
The above is the detailed content of How to prevent program B from archiving/deleting files currently open by program A in Go?. For more information, please follow other related articles on the PHP Chinese website!