mirror of
https://github.com/golang/go
synced 2024-11-21 22:54:40 -07:00
go spec, effective go: cleanups
Removed most of the detailed examples about handing panics from the go spec since it's now covered by Effective Go. R=r, rsc, iant, ken2 CC=golang-dev https://golang.org/cl/4128058
This commit is contained in:
parent
4a14bc524b
commit
76f3228520
@ -824,7 +824,7 @@ executions. Here's a silly example.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
defer fmt.Printf("%d ", i)
|
defer fmt.Printf("%d ", i)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
@ -1486,7 +1486,7 @@ for a min function that chooses the least of a list of integers:
|
|||||||
func Min(a ...int) int {
|
func Min(a ...int) int {
|
||||||
min := int(^uint(0) >> 1) // largest int
|
min := int(^uint(0) >> 1) // largest int
|
||||||
for _, i := range a {
|
for _, i := range a {
|
||||||
if i < min {
|
if i < min {
|
||||||
min = i
|
min = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2670,7 +2670,7 @@ suppresses the usual check for a <code>return</code> statement.
|
|||||||
// A toy implementation of cube root using Newton's method.
|
// A toy implementation of cube root using Newton's method.
|
||||||
func CubeRoot(x float64) float64 {
|
func CubeRoot(x float64) float64 {
|
||||||
z := x/3 // Arbitrary intitial value
|
z := x/3 // Arbitrary intitial value
|
||||||
for i := 0; i < 1e6; i++ {
|
for i := 0; i < 1e6; i++ {
|
||||||
prevz := z
|
prevz := z
|
||||||
z -= (z*z*z-x) / (3*z*z)
|
z -= (z*z*z-x) / (3*z*z)
|
||||||
if veryClose(z, prevz) {
|
if veryClose(z, prevz) {
|
||||||
@ -2727,7 +2727,7 @@ inside a server without killing the other executing goroutines.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func server(workChan <-chan *Work) {
|
func server(workChan <-chan *Work) {
|
||||||
for work := range workChan {
|
for work := range workChan {
|
||||||
go safelyDo(work)
|
go safelyDo(work)
|
||||||
}
|
}
|
||||||
@ -2751,7 +2751,16 @@ calling <code>recover</code> handles the condition completely.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Note that with this recovery pattern in place, the <code>do</code>
|
Because <code>recover</code> always returns <code>nil</code> unless called directly
|
||||||
|
from a deferred function, deferred code can call library routines that themselves
|
||||||
|
use <code>panic</code> and <code>recover</code> without failing. As an example,
|
||||||
|
the deferred function in <code>safelyDo</code> might call a logging function before
|
||||||
|
calling <code>recover</code>, and that logging code would run unaffected
|
||||||
|
by the panicking state.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
With our recovery pattern in place, the <code>do</code>
|
||||||
function (and anything it calls) can get out of any bad situation
|
function (and anything it calls) can get out of any bad situation
|
||||||
cleanly by calling <code>panic</code>. We can use that idea to
|
cleanly by calling <code>panic</code>. We can use that idea to
|
||||||
simplify error handling in complex software. Let's look at an
|
simplify error handling in complex software. Let's look at an
|
||||||
|
121
doc/go_spec.html
121
doc/go_spec.html
@ -1,5 +1,5 @@
|
|||||||
<!-- title The Go Programming Language Specification -->
|
<!-- title The Go Programming Language Specification -->
|
||||||
<!-- subtitle Version of February 3, 2011 -->
|
<!-- subtitle Version of February 4, 2011 -->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
TODO
|
TODO
|
||||||
@ -4646,13 +4646,6 @@ func panic(interface{})
|
|||||||
func recover() interface{}
|
func recover() interface{}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
|
||||||
<span class="alert">TODO: Most of this text could move to the respective
|
|
||||||
comments in <code>runtime.go</code> once the functions are implemented.
|
|
||||||
They are here, at least for now, for reference and discussion.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
When a function <code>F</code> calls <code>panic</code>, normal
|
When a function <code>F</code> calls <code>panic</code>, normal
|
||||||
execution of <code>F</code> stops immediately. Any functions whose
|
execution of <code>F</code> stops immediately. Any functions whose
|
||||||
@ -4668,117 +4661,43 @@ the argument to <code>panic</code>. This termination sequence is
|
|||||||
called <i>panicking</i>.
|
called <i>panicking</i>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
panic(42)
|
||||||
|
panic("unreachable")
|
||||||
|
panic(Error("cannot parse"))
|
||||||
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>recover</code> function allows a program to manage behavior
|
The <code>recover</code> function allows a program to manage behavior
|
||||||
of a panicking goroutine. Executing a <code>recover</code> call
|
of a panicking goroutine. Executing a <code>recover</code> call
|
||||||
inside a deferred function (but not any function called by it) stops
|
<i>inside</i> a deferred function (but not any function called by it) stops
|
||||||
the panicking sequence by restoring normal execution, and retrieves
|
the panicking sequence by restoring normal execution, and retrieves
|
||||||
the error value passed to the call of <code>panic</code>. If
|
the error value passed to the call of <code>panic</code>. If
|
||||||
<code>recover</code> is called outside the deferred function it will
|
<code>recover</code> is called outside the deferred function it will
|
||||||
not stop a panicking sequence. In this case, and when the goroutine
|
not stop a panicking sequence. In this case, or when the goroutine
|
||||||
is not panicking, <code>recover</code> returns <code>nil</code>.
|
is not panicking, or if the argument supplied to <code>panic</code>
|
||||||
|
was <code>nil</code>, <code>recover</code> returns <code>nil</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the function defined here,
|
The <code>protect</code> function in the example below invokes
|
||||||
|
the function argument <code>g</code> and protects callers from
|
||||||
|
run-time panics raised by <code>g</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func f(hideErrors bool) {
|
func protect(g func()) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
log.Println("done") // Println executes normally even in there is a panic
|
||||||
if x := recover(); x != nil {
|
if x := recover(); x != nil {
|
||||||
println("panicking with value", x)
|
log.Printf("runtime panic: %v", x)
|
||||||
if !hideErrors {
|
|
||||||
panic(x) // go back to panicking
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
println("function returns normally") // executes only when hideErrors==true
|
}
|
||||||
}()
|
log.Println("start")
|
||||||
println("before")
|
g()
|
||||||
p()
|
|
||||||
println("after") // never executes
|
|
||||||
}
|
|
||||||
|
|
||||||
func p() {
|
|
||||||
panic(3)
|
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
|
||||||
is called with <code>hideErrors=true</code>, it prints
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
before
|
|
||||||
panicking with value 3
|
|
||||||
function returns normally
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
and resumes normal execution in the function that called <code>f</code>. Otherwise, it prints
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
before
|
|
||||||
panicking with value 3
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
and, absent further <code>recover</code> calls, terminates the program.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Since deferred functions run before assigning the return values to the caller
|
|
||||||
of the deferring function, a deferred invocation of a function literal may modify the
|
|
||||||
invoking function's return values in the event of a panic. This permits a function to protect its
|
|
||||||
caller from panics that occur in functions it calls.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
func IsPrintable(s string) (ok bool) {
|
|
||||||
ok = true
|
|
||||||
defer func() {
|
|
||||||
if recover() != nil {
|
|
||||||
println("input is not printable")
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
// Panicking has stopped; execution will resume normally in caller.
|
|
||||||
// The return value will be true normally, false if a panic occurred.
|
|
||||||
}()
|
|
||||||
panicIfNotPrintable(s) // will panic if validations fails.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<!---
|
|
||||||
<p>
|
|
||||||
A deferred function that calls <code>recover</code> will see the
|
|
||||||
argument passed to <code>panic</code>. However, functions called
|
|
||||||
<i>from</i> the deferred function run normally, without behaving as
|
|
||||||
though they are panicking. This allows deferred code to run normally
|
|
||||||
in case recovery is necessary and guarantees that functions that manage
|
|
||||||
their own panics will not fail incorrectly. The function
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
func g() {
|
|
||||||
s := ReadString()
|
|
||||||
defer func() {
|
|
||||||
if IsPrintable(s) {
|
|
||||||
println("finished processing", s)
|
|
||||||
} else {
|
|
||||||
println("finished processing unprintable string")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
Analyze(s)
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
will not cause <code>IsPrintable</code> to print <code>"input is not printable"</code>
|
|
||||||
due to a <code>panic</code> triggered by the call to <code>Analyze</code>.
|
|
||||||
</p>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<h3 id="Bootstrapping">Bootstrapping</h3>
|
<h3 id="Bootstrapping">Bootstrapping</h3>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user