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:
parent
0eb0afde9a
commit
781462dc46
@ -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—much more commonly—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>—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 < len(a); i++ {
|
11 for i := 0; i < 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(&[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>—a type followed by a
|
<p>
|
||||||
brace-bounded
|
To call the function, we slice the array. This intricate call (we'll show
|
||||||
expression—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>&</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(&[...]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—using empty brackets and no
|
In practice, unless you're meticulous about storage layout within a
|
||||||
<code>&</code>—is all you need:
|
data structure, a slice itself—using empty brackets with no size—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(&buf); true {
|
18 switch nr, er := f.Read(buf[:]); true {
|
||||||
19 case nr < 0:
|
19 case nr < 0:
|
||||||
20 fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f.String(), er.String())
|
20 fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", 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(&buf); {
|
60 switch nr, er := r.Read(buf[:]); {
|
||||||
61 case nr < 0:
|
61 case nr < 0:
|
||||||
62 fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
|
62 fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
|
||||||
63 os.Exit(1)
|
63 os.Exit(1)
|
||||||
|
@ -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—much more commonly—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>—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}"—a type followed by a
|
|
||||||
brace-bounded
|
To call the function, we slice the array. This intricate call (we'll show
|
||||||
expression—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 "&"
|
|
||||||
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(&[...]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—using empty brackets and no
|
In practice, unless you're meticulous about storage layout within a
|
||||||
"&"—is all you need:
|
data structure, a slice itself—using empty brackets with no size—is all you need:
|
||||||
|
|
||||||
s := sum([]int{1,2,3})
|
s := sum([]int{1,2,3})
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user