1
0
mirror of https://github.com/golang/go synced 2024-11-21 20:24:50 -07:00

Effective Go: update ... discussion.

R=rsc
CC=golang-dev
https://golang.org/cl/1698041
This commit is contained in:
Rob Pike 2010-06-14 22:40:35 -07:00
parent c9172fb2a3
commit 6c08859b0e

View File

@ -245,7 +245,7 @@ var (
countLock sync.Mutex countLock sync.Mutex
inputCount uint32 inputCount uint32
outputCount uint32 outputCount uint32
errorCount uint32 errorCount uint32
) )
</pre> </pre>
@ -423,7 +423,7 @@ if i &lt; f() // wrong!
<h2 id="control-structures">Control structures</h2> <h2 id="control-structures">Control structures</h2>
<p> <p>
The control structures of Go are related to those of C but different The control structures of Go are related to those of C but differ
in important ways. in important ways.
There is no <code>do</code> or <code>while</code> loop, only a There is no <code>do</code> or <code>while</code> loop, only a
slightly generalized slightly generalized
@ -1308,22 +1308,24 @@ to print in the format
Our <code>String()</code> method is able to call <code>Sprintf</code> because the Our <code>String()</code> method is able to call <code>Sprintf</code> because the
print routines are fully reentrant and can be used recursively. print routines are fully reentrant and can be used recursively.
We can even go one step further and pass a print routine's arguments directly to another such routine. We can even go one step further and pass a print routine's arguments directly to another such routine.
The signature of <code>Printf</code> uses the <code>...</code> The signature of <code>Printf</code> uses the type <code>...interface{}</code>
type for its final argument to specify that an arbitrary number of parameters can appear for its final argument to specify that an arbitrary number of parameters (of arbitrary type)
after the format. can appear after the format.
</p> </p>
<pre> <pre>
func Printf(format string, v ...) (n int, errno os.Error) { func Printf(format string, v ...interface{}) (n int, errno os.Error) {
</pre> </pre>
<p> <p>
Within the function <code>Printf</code>, <code>v</code> is a variable that can be passed, Within the function <code>Printf</code>, <code>v</code> acts like a variable of type
for instance, to another print routine. Here is the implementation of the <code>[]interface{}</code> but if it is passed to another variadic function, it acts like
a regular list of arguments.
Here is the implementation of the
function <code>log.Stderr</code> we used above. It passes its arguments directly to function <code>log.Stderr</code> we used above. It passes its arguments directly to
<code>fmt.Sprintln</code> for the actual formatting. <code>fmt.Sprintln</code> for the actual formatting.
</p> </p>
<pre> <pre>
// Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr). // Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr).
func Stderr(v ...) { func Stderr(v ...interface{}) {
stderr.Output(2, fmt.Sprintln(v)) // Output takes parameters (int, string) stderr.Output(2, fmt.Sprintln(v)) // Output takes parameters (int, string)
} }
</pre> </pre>
@ -1331,6 +1333,21 @@ func Stderr(v ...) {
There's even more to printing than we've covered here. See the <code>godoc</code> documentation There's even more to printing than we've covered here. See the <code>godoc</code> documentation
for package <code>fmt</code> for the details. for package <code>fmt</code> for the details.
</p> </p>
<p>
By the way, a <code>...</code> parameter can be of a specific type, for instance <code>...int</code>
for a min function that chooses the least of a list of integers:
</p>
<pre>
func Min(a ...int) int {
min := int(^uint(0) >> 1) // largest int
for _, i := range a {
if i < min {
min = i
}
}
return min
}
</pre>
<h2 id="initialization">Initialization</h2> <h2 id="initialization">Initialization</h2>
@ -1948,7 +1965,7 @@ type Job struct {
<p> <p>
The <code>Job</code> type now has the <code>Log</code>, <code>Logf</code> The <code>Job</code> type now has the <code>Log</code>, <code>Logf</code>
and other and other
methods of <code>log.Logger</code>. We could have given the <code>Logger</code> methods of <code>*log.Logger</code>. We could have given the <code>Logger</code>
a field name, of course, but it's not necessary to do so. And now, once a field name, of course, but it's not necessary to do so. And now, once
initialized, we can initialized, we can
log to the <code>Job</code>: log to the <code>Job</code>:
@ -1993,7 +2010,7 @@ of <code>Job</code> would dominate it.
</p> </p>
<p> <p>
Second, if the same name appears at the same nesting level, it is usually an error; Second, if the same name appears at the same nesting level, it is usually an error;
it would be erroneous to embed <code>log.Logger</code> if <code>Job</code> struct it would be erroneous to embed <code>log.Logger</code> if the <code>Job</code> struct
contained another field or method called <code>Logger</code>. contained another field or method called <code>Logger</code>.
However, if the duplicate name is never mentioned in the program outside the type definition, it is OK. However, if the duplicate name is never mentioned in the program outside the type definition, it is OK.
This qualification provides some protection against changes made to types embedded from outside; there This qualification provides some protection against changes made to types embedded from outside; there