Reputation: 9
When I do some file operations with golang, I firstly open a file and add the close() into defer list, then I try to rename that file. If I close the file manually, the defer will close it again. If I wait for the defer to close it, the rename will cause error because it is not closed yey. Code as below
func main() {
pfile1, _ := os.Open("myfile.log")
defer pfile1.Close() //It will be closed again.
...
...
pfile1.Close() //I have to close it before rename it.
os.Rename("myfile.log", "myfile1.log")
}
I found some ugly solution, such as create another function to separate the open file, does any better solution that below?
func main() {
var pfile1 *os.File
ugly_solution(pfile1)
os.Rename("myfile.log", "myfile1.log")
}
func ugly_solution(file *os.File) {
file, _ = os.Open("myfile.log")
defer file.Close()
}
Upvotes: 0
Views: 5463
Reputation: 31
In situation like in your sample
Maybe you want to follow this scenario:
In that case where you want to follow OS system action of underlying files maybe you want to simply not deferring the close on IO.file since you want to get the Error returned by the close function itself.
Also, in that case you maybe want to operate a file.sync() too.
See https://www.joeshaw.org/dont-defer-close-on-writable-files/
Upvotes: 0
Reputation: 2884
You can put both closing and renaming the file in the defer:
func main() {
pfile1, _ := os.Open("myfile.log")
defer func(){
pfile1.Close()
os.Rename("myfile.log", "myfile1.log")
}()
...
...
}
Upvotes: 2
Reputation: 176382
There are a few things that are not clear to me about your code.
First of all, why do you open the file before renaming it? This is not required by the os.Rename
function. The function takes two strings representing the old and new file name, there is no need to pass a file pointer.
func main() {
...
...
os.Rename("myfile.log", "myfile1.log")
}
Assuming you need to make changes to the file content (which doesn't seem to be the case given the ugly_solution
method) and you have to open the file, then why deferring file.Close()
? You don't have to defer the method if you need it to be called explicitly somewhere in the same method. Simply call it.
func main() {
pfile1, _ := os.Open("myfile.log")
...
...
pfile1.Close()
os.Rename("myfile.log", "myfile1.log")
}
Upvotes: 2