manage the loop.
</p>
<pre>
-var m map[string]int
+for key, value := range oldMap {
+ newMap[key] = value
+}
+</pre>
+
+<p>
+If you only need the first item in the range (the key or index), drop the second:
+</p>
+<pre>
+for key := range m {
+ if expired(key) {
+ delete(m, key)
+ }
+}
+</pre>
+
+<p>
+If you only need the second item in the range (the value), use the <em>blank identifier</em>, an underscore, to discard the first:
+</p>
+<pre>
sum := 0
-for _, value := range m { // key is unused
+for _, value := range array {
sum += value
}
</pre>
Here's a comparison routine for byte arrays that uses two
<code>switch</code> statements:
<pre>
-// Compare returns an integer comparing the two byte arrays
+// Compare returns an integer comparing the two byte arrays,
// lexicographically.
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b
func Compare(a, b []byte) int {
Let's talk about <code>new</code> first.
It's a built-in function that allocates memory, but unlike its namesakes
in some other languages it does not <em>initialize</em> the memory,
-it only <em>zeroes</em> it.
+it only <em>zeros</em> it.
That is,
<code>new(T)</code> allocates zeroed storage for a new item of type
<code>T</code> and returns its address, a value of type <code>*T</code>.
</pre>
<p>
Such slicing is common and efficient. In fact, leaving efficiency aside for
-the moment, this snippet would also read the first 32 bytes of the buffer.
+the moment, the following snippet would also read the first 32 bytes of the buffer.
</p>
<pre>
var n int
</pre>
<p>
To test for presence in the map without worrying about the actual value,
-you can use the <em>blank identifier</em>, a simple underscore (<code>_</code>).
+you can use the blank identifier (<code>_</code>).
The blank identifier can be assigned or declared with any value of any type, with the
value discarded harmlessly. For testing just presence in a map, use the blank
identifier in place of the usual variable for the value.
</p>
{{code "/doc/progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}}
<p>
-(The <code>float64</code> conversions prevent <code>Sprintf</code>
-from recurring back through the <code>String</code> method for
-<code>ByteSize</code>.)
The expression <code>YB</code> prints as <code>1.00YB</code>,
while <code>ByteSize(1e13)</code> prints as <code>9.09TB</code>.
</p>
+<p>
+Note that it's fine to call <code>Sprintf</code> and friends in the
+implementation of <code>String</code> methods, but beware of
+recurring into the <code>String</code> method through the nested
+<code>Sprintf</code> call using a string format
+(<code>%s</code>, <code>%q</code>, <code>%v</code>, <code>%x</code> or <code>%X</code>).
+The <code>ByteSize</code> implementation of <code>String</code> is safe
+because it calls <code>Sprintf</code> with <code>%f</code>.
+</p>
+
<h3 id="variables">Variables</h3>
<p>
<p>
Another application of these ideas is to parallelize a calculation
across multiple CPU cores. If the calculation can be broken into
-separate pieces, it can be parallelized, with a channel to signal
-when each piece completes.
+separate pieces that can execute independently, it can be parallelized,
+with a channel to signal when each piece completes.
</p>
<p>
Let's say we have an expensive operation to perform on a vector of items,
</pre>
<p>
-The current implementation of <code>gc</code> (<code>6g</code>, etc.)
+The current implementation of the Go runtime
will not parallelize this code by default.
It dedicates only a single core to user-level processing. An
arbitrary number of goroutines can be blocked in system calls, but
for the template package for a more thorough discussion.
</p>
<p>
-And there you have it: a useful webserver in a few lines of code plus some
+And there you have it: a useful web server in a few lines of code plus some
data-driven HTML text.
Go is powerful enough to make a lot happen in a few lines.
</p>
func (b ByteSize) String() string {
switch {
case b >= YB:
- return fmt.Sprintf("%.2fYB", float64(b/YB))
+ return fmt.Sprintf("%.2fYB", b/YB)
case b >= ZB:
- return fmt.Sprintf("%.2fZB", float64(b/ZB))
+ return fmt.Sprintf("%.2fZB", b/ZB)
case b >= EB:
- return fmt.Sprintf("%.2fEB", float64(b/EB))
+ return fmt.Sprintf("%.2fEB", b/EB)
case b >= PB:
- return fmt.Sprintf("%.2fPB", float64(b/PB))
+ return fmt.Sprintf("%.2fPB", b/PB)
case b >= TB:
- return fmt.Sprintf("%.2fTB", float64(b/TB))
+ return fmt.Sprintf("%.2fTB", b/TB)
case b >= GB:
- return fmt.Sprintf("%.2fGB", float64(b/GB))
+ return fmt.Sprintf("%.2fGB", b/GB)
case b >= MB:
- return fmt.Sprintf("%.2fMB", float64(b/MB))
+ return fmt.Sprintf("%.2fMB", b/MB)
case b >= KB:
- return fmt.Sprintf("%.2fKB", float64(b/KB))
+ return fmt.Sprintf("%.2fKB", b/KB)
}
- return fmt.Sprintf("%.2fB", float64(b))
+ return fmt.Sprintf("%.2fB", b)
}
func main() {