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

doc/tutorial: update for slice changes.

Awaiting the lower-bound change before checkin.

Fixes #1067.

R=rsc, iant, gri
CC=golang-dev
https://golang.org/cl/2105043
This commit is contained in:
Rob Pike 2010-09-10 13:53:18 +10:00
parent 0eb0afde9a
commit 781462dc46
5 changed files with 78 additions and 66 deletions

View File

@ -286,14 +286,15 @@ In Go, since arrays are values, it's meaningful (and useful) to talk
about pointers to arrays. about pointers to arrays.
<p> <p>
The size of the array is part of its type; however, one can declare The size of the array is part of its type; however, one can declare
a <i>slice</i> variable, to which one can assign a pointer to a <i>slice</i> variable to hold a reference to any array, of any size,
any array with the same element type.
with the same element type or&mdash;much more commonly&mdash;a <i>slice A <i>slice
expression</i> of the form <code>a[low : high]</code>, representing expression</i> has the form <code>a[low : high]</code>, representing
the subarray indexed by <code>low</code> through <code>high-1</code>. the internal array indexed from <code>low</code> through <code>high-1</code>; the resulting
Slices look a lot like arrays but have slice is indexed from <code>0</code> through <code>high-low-1</code>.
In short, slices look a lot like arrays but with
no explicit size (<code>[]</code> vs. <code>[10]</code>) and they reference a segment of no explicit size (<code>[]</code> vs. <code>[10]</code>) and they reference a segment of
an underlying, often anonymous, regular array. Multiple slices an underlying, usually anonymous, regular array. Multiple slices
can share data if they represent pieces of the same array; can share data if they represent pieces of the same array;
multiple arrays can never share data. multiple arrays can never share data.
<p> <p>
@ -302,17 +303,28 @@ regular arrays; they're more flexible, have reference semantics,
and are efficient. What they lack is the precise control of storage and are efficient. What they lack is the precise control of storage
layout of a regular array; if you want to have a hundred elements layout of a regular array; if you want to have a hundred elements
of an array stored within your structure, you should use a regular of an array stored within your structure, you should use a regular
array. array. To create one, use a compound value <i>constructor</i>&mdash;an
expression formed
from a type followed by a brace-bounded expression like this:
<p>
<pre>
[3]int{1,2,3}
</pre>
<p>
In this case the constructor builds an array of 3 <code>ints</code>.
<p> <p>
When passing an array to a function, you almost always want When passing an array to a function, you almost always want
to declare the formal parameter to be a slice. When you call to declare the formal parameter to be a slice. When you call
the function, take the address of the array and Go will the function, slice the array to create
create (efficiently) a slice reference and pass that. (efficiently) a slice reference and pass that.
By default, the lower and upper bounds of a slice match the
ends of the existing object, so the concise notation <code>[:]</code>
will slice the whole array.
<p> <p>
Using slices one can write this function (from <code>sum.go</code>): Using slices one can write this function (from <code>sum.go</code>):
<p> <p>
<pre> <!-- progs/sum.go /sum/ /^}/ --> <pre> <!-- progs/sum.go /sum/ /^}/ -->
09 func sum(a []int) int { // returns an int 09 func sum(a []int) int { // returns an int
10 s := 0 10 s := 0
11 for i := 0; i &lt; len(a); i++ { 11 for i := 0; i &lt; len(a); i++ {
12 s += a[i] 12 s += a[i]
@ -321,32 +333,27 @@ Using slices one can write this function (from <code>sum.go</code>):
15 } 15 }
</pre> </pre>
<p> <p>
and invoke it like this:
<p>
<pre> <!-- progs/sum.go /1,2,3/ -->
19 s := sum(&amp;[3]int{1,2,3}) // a slice of the array is passed to sum
</pre>
<p>
Note how the return type (<code>int</code>) is defined for <code>sum()</code> by stating it Note how the return type (<code>int</code>) is defined for <code>sum()</code> by stating it
after the parameter list. after the parameter list.
The expression <code>[3]int{1,2,3}</code>&mdash;a type followed by a <p>
brace-bounded To call the function, we slice the array. This intricate call (we'll show
expression&mdash;is a constructor for a value, in this case an array a simpler way in a moment) constructs
of 3 <code>ints</code>. an array and slices it:
Putting an <code>&amp;</code> <p>
in front gives us the address of a unique instance of the value. We pass the <pre>
pointer to <code>sum()</code> by (implicitly) promoting it to a slice. s := sum([3]int{1,2,3}[:])
</pre>
<p> <p>
If you are creating a regular array but want the compiler to count the If you are creating a regular array but want the compiler to count the
elements for you, use <code>...</code> as the array size: elements for you, use <code>...</code> as the array size:
<p> <p>
<pre> <pre>
s := sum(&amp;[...]int{1,2,3}) s := sum([...]int{1,2,3}[:])
</pre> </pre>
<p> <p>
In practice, though, unless you're meticulous about storage layout within a That's fussier than necessary, though.
data structure, a slice itself&mdash;using empty brackets and no In practice, unless you're meticulous about storage layout within a
<code>&amp;</code>&mdash;is all you need: data structure, a slice itself&mdash;using empty brackets with no size&mdash;is all you need:
<p> <p>
<pre> <pre>
s := sum([]int{1,2,3}) s := sum([]int{1,2,3})
@ -687,7 +694,7 @@ Building on the <code>file</code> package, here's a simple version of the Unix u
15 const NBUF = 512 15 const NBUF = 512
16 var buf [NBUF]byte 16 var buf [NBUF]byte
17 for { 17 for {
18 switch nr, er := f.Read(&amp;buf); true { 18 switch nr, er := f.Read(buf[:]); true {
19 case nr &lt; 0: 19 case nr &lt; 0:
20 fmt.Fprintf(os.Stderr, &quot;cat: error reading from %s: %s\n&quot;, f.String(), er.String()) 20 fmt.Fprintf(os.Stderr, &quot;cat: error reading from %s: %s\n&quot;, f.String(), er.String())
21 os.Exit(1) 21 os.Exit(1)
@ -803,7 +810,7 @@ and use it from within a mostly unchanged <code>cat()</code> function:
57 r = newRotate13(r) 57 r = newRotate13(r)
58 } 58 }
59 for { 59 for {
60 switch nr, er := r.Read(&amp;buf); { 60 switch nr, er := r.Read(buf[:]); {
61 case nr &lt; 0: 61 case nr &lt; 0:
62 fmt.Fprintf(os.Stderr, &quot;cat: error reading from %s: %s\n&quot;, r.String(), er.String()) 62 fmt.Fprintf(os.Stderr, &quot;cat: error reading from %s: %s\n&quot;, r.String(), er.String())
63 os.Exit(1) 63 os.Exit(1)

View File

@ -227,14 +227,15 @@ In Go, since arrays are values, it's meaningful (and useful) to talk
about pointers to arrays. about pointers to arrays.
The size of the array is part of its type; however, one can declare The size of the array is part of its type; however, one can declare
a <i>slice</i> variable, to which one can assign a pointer to a <i>slice</i> variable to hold a reference to any array, of any size,
any array with the same element type.
with the same element type or&mdash;much more commonly&mdash;a <i>slice A <i>slice
expression</i> of the form "a[low : high]", representing expression</i> has the form "a[low : high]", representing
the subarray indexed by "low" through "high-1". the internal array indexed from "low" through "high-1"; the resulting
Slices look a lot like arrays but have slice is indexed from "0" through "high-low-1".
In short, slices look a lot like arrays but with
no explicit size ("[]" vs. "[10]") and they reference a segment of no explicit size ("[]" vs. "[10]") and they reference a segment of
an underlying, often anonymous, regular array. Multiple slices an underlying, usually anonymous, regular array. Multiple slices
can share data if they represent pieces of the same array; can share data if they represent pieces of the same array;
multiple arrays can never share data. multiple arrays can never share data.
@ -243,39 +244,43 @@ regular arrays; they're more flexible, have reference semantics,
and are efficient. What they lack is the precise control of storage and are efficient. What they lack is the precise control of storage
layout of a regular array; if you want to have a hundred elements layout of a regular array; if you want to have a hundred elements
of an array stored within your structure, you should use a regular of an array stored within your structure, you should use a regular
array. array. To create one, use a compound value <i>constructor</i>&mdash;an
expression formed
from a type followed by a brace-bounded expression like this:
[3]int{1,2,3}
In this case the constructor builds an array of 3 "ints".
When passing an array to a function, you almost always want When passing an array to a function, you almost always want
to declare the formal parameter to be a slice. When you call to declare the formal parameter to be a slice. When you call
the function, take the address of the array and Go will the function, slice the array to create
create (efficiently) a slice reference and pass that. (efficiently) a slice reference and pass that.
By default, the lower and upper bounds of a slice match the
ends of the existing object, so the concise notation "[:]"
will slice the whole array.
Using slices one can write this function (from "sum.go"): Using slices one can write this function (from "sum.go"):
--PROG progs/sum.go /sum/ /^}/ --PROG progs/sum.go /sum/ /^}/
and invoke it like this:
--PROG progs/sum.go /1,2,3/
Note how the return type ("int") is defined for "sum()" by stating it Note how the return type ("int") is defined for "sum()" by stating it
after the parameter list. after the parameter list.
The expression "[3]int{1,2,3}"&mdash;a type followed by a
brace-bounded To call the function, we slice the array. This intricate call (we'll show
expression&mdash;is a constructor for a value, in this case an array a simpler way in a moment) constructs
of 3 "ints". an array and slices it:
Putting an "&amp;"
in front gives us the address of a unique instance of the value. We pass the s := sum([3]int{1,2,3}[:])
pointer to "sum()" by (implicitly) promoting it to a slice.
If you are creating a regular array but want the compiler to count the If you are creating a regular array but want the compiler to count the
elements for you, use "..." as the array size: elements for you, use "..." as the array size:
s := sum(&amp;[...]int{1,2,3}) s := sum([...]int{1,2,3}[:])
In practice, though, unless you're meticulous about storage layout within a That's fussier than necessary, though.
data structure, a slice itself&mdash;using empty brackets and no In practice, unless you're meticulous about storage layout within a
"&amp;"&mdash;is all you need: data structure, a slice itself&mdash;using empty brackets with no size&mdash;is all you need:
s := sum([]int{1,2,3}) s := sum([]int{1,2,3})

View File

@ -15,11 +15,11 @@ func cat(f *file.File) {
const NBUF = 512 const NBUF = 512
var buf [NBUF]byte var buf [NBUF]byte
for { for {
switch nr, er := f.Read(&buf); true { switch nr, er := f.Read(buf[:]); true {
case nr < 0: case nr < 0:
fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f.String(), er.String()) fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f.String(), er.String())
os.Exit(1) os.Exit(1)
case nr == 0: // EOF case nr == 0: // EOF
return return
case nr > 0: case nr > 0:
if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr { if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
@ -30,7 +30,7 @@ func cat(f *file.File) {
} }
func main() { func main() {
flag.Parse() // Scans the arg list and sets up flags flag.Parse() // Scans the arg list and sets up flags
if flag.NArg() == 0 { if flag.NArg() == 0 {
cat(file.Stdin) cat(file.Stdin)
} }

View File

@ -15,10 +15,10 @@ var rot13Flag = flag.Bool("rot13", false, "rot13 the input")
func rot13(b byte) byte { func rot13(b byte) byte {
if 'a' <= b && b <= 'z' { if 'a' <= b && b <= 'z' {
b = 'a' + ((b - 'a') + 13) % 26 b = 'a' + ((b-'a')+13)%26
} }
if 'A' <= b && b <= 'Z' { if 'A' <= b && b <= 'Z' {
b = 'A' + ((b - 'A') + 13) % 26 b = 'A' + ((b-'A')+13)%26
} }
return b return b
} }
@ -29,7 +29,7 @@ type reader interface {
} }
type rotate13 struct { type rotate13 struct {
source reader source reader
} }
func newRotate13(source reader) *rotate13 { func newRotate13(source reader) *rotate13 {
@ -57,11 +57,11 @@ func cat(r reader) {
r = newRotate13(r) r = newRotate13(r)
} }
for { for {
switch nr, er := r.Read(&buf); { switch nr, er := r.Read(buf[:]); {
case nr < 0: case nr < 0:
fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String()) fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
os.Exit(1) os.Exit(1)
case nr == 0: // EOF case nr == 0: // EOF
return return
case nr > 0: case nr > 0:
nw, ew := file.Stdout.Write(buf[0:nr]) nw, ew := file.Stdout.Write(buf[0:nr])
@ -73,7 +73,7 @@ func cat(r reader) {
} }
func main() { func main() {
flag.Parse() // Scans the arg list and sets up flags flag.Parse() // Scans the arg list and sets up flags
if flag.NArg() == 0 { if flag.NArg() == 0 {
cat(file.Stdin) cat(file.Stdin)
} }

View File

@ -6,7 +6,7 @@ package main
import "fmt" import "fmt"
func sum(a []int) int { // returns an int func sum(a []int) int { // returns an int
s := 0 s := 0
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
s += a[i] s += a[i]
@ -16,6 +16,6 @@ func sum(a []int) int { // returns an int
func main() { func main() {
s := sum(&[3]int{1,2,3}) // a slice of the array is passed to sum s := sum([3]int{1, 2, 3}[:]) // a slice of the array is passed to sum
fmt.Print(s, "\n") fmt.Print(s, "\n")
} }