And can you provide an example. In my case, I need 3 operations:
func Write(fname, content string) {
open()
write()
close()
}
Where should I put the defer statement?
I'd like to open a file, write several lines of strings, and finally
close the file.
As there are several places that we can meet errors, we have to make
sure the file is closed,
despite possible errors.
Go has the defer statement.
My understanding is that its purpose is guarantee the close operation,
in this file case.
Is my understanding right? If I properly handle every possible error,
need I use defer any more?
Can I call close() and the end, without the defer statement?
And can you provide an example. In my case, I need 3 operations:
func Write(fname, content string) {
open()
write()
close()
}
Where should I put the defer statement?
Not like normal error, panic is out of my control, right?
Where can I find the document of panic?
> Yes. Then you risk not closing the file if a panic happens.Not like normal error, panic is out of my control, right?
Where can I find the document of panic?
func doWrite() (err os.Error) {
f, err := os.Open("somefile", os.O_RDWR | os.O_CREATE, 0666)
if err != nil {
return
}
defer f.Close()
_, err = f.Write([]byte("An array of bytes"))
if err != nil {
return // f.Close() will automatically be called now
}
// some other logic here
return // f.Close() will automatically be called now
}
You could, just as easily, call f.close() before any return statement
in the function. That would be fine.
Don't confuse defer with panic/resolve. The panic/resolve mechanism
uses defer, but defer is a useful feature on its own.
You shouldn't put defer statements in your code to guard against
unexpected panics. No well-written library should let a panic escape
the package itself.
In this specific case, defer is simply a nice way of avoiding typing
f.Close() more than once.
Andrew
> --
> To unsubscribe, reply using "remove me" as the subject.
>
> In this specific case, defer is simply a nice way of avoiding typing
> f.Close() more than once.
more importantly, defer lets the programmer keep related actions in
proximity to each other in the code -- seeing the 'defer close()'
statement right after the Open (i wouldn't even separate it with an
empty line) tells me much more about the action than i would otherwise
know: "whatever else happens, this needs to close when i'm done". i
know locks are unpopular in Go, but i'm positive the defer statement
came about from a desire to solve the problem of unlocking held locks
in multiple code paths, a source of deadlocks in a lot of software,
even one involving channels and coroutines. defer is a very elegant
solution (and a crutch for sloppy programmers) and it does keep
services running.
On 4月13日, 上午7時17分, Andrew Gerrand <a...@golang.org> wrote:
> A simple example:
>
> func doWrite() (err os.Error) {
> f, err := os.Open("somefile", os.O_RDWR | os.O_CREATE, 0666)
> if err != nil {
> return
> }
>
> defer f.Close()
>
> _, err = f.Write([]byte("An array of bytes"))
> if err != nil {
> return // f.Close() will automatically be called now
> }
>
> // some other logic here
>
> return // f.Close() will automatically be called now
>
> }
>
> You could, just as easily, call f.close() before any return statement
> in the function. That would be fine.
>
> Don't confuse defer with panic/resolve. The panic/resolve mechanism
> uses defer, but defer is a useful feature on its own.
>
> You shouldn't put defer statements in your code to guard against
> unexpected panics. No well-written library should let a panic escape
> the package itself.
>
> In this specific case, defer is simply a nice way of avoiding typing
> f.Close() more than once.
>
> Andrew
>
Then it does not matter, as the operating system will close and flush
any open file descriptors on exit.
--Benny.
David
Or you can defer the call to os.Exit, with something like:
package main
import ("bufio"; "os")
type ExitCode int
func End(){
if x := recover(); x != nil {
if c, ok := x.(ExitCode); ok {
os.Exit(int(c))
}
panic(x)
}
}
func Exit(code int){
panic(ExitCode(code))
}
func main(){
defer End()
b := bufio.NewWriter(os.Stdout)
defer b.Flush()
b.Write([]byte("Halo!\n"))
Exit(666)
}
Maybe os.Exit() should call the defered functions?
--
- yiyus || JGL . 4l77.com
Yeah, that's how I'd prefer for os.Exit to work, although there is
some vagueness in my mind as to how panics are handled in goroutines.
Obviously a panic in a goroutine will kill the entire program, but
does it trigger all the deferred functions in all other goroutines? I
would hope so, but if not, then your Exit may not work properly.
David