mirror of
https://github.com/golang/go
synced 2024-11-13 17:20:22 -07:00
Effective Go: update ... discussion.
R=rsc CC=golang-dev https://golang.org/cl/1698041
This commit is contained in:
parent
c9172fb2a3
commit
6c08859b0e
@ -423,7 +423,7 @@ if i < 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
|
||||||
|
Loading…
Reference in New Issue
Block a user