Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
34356e9a
Commit
34356e9a
authored
Dec 16, 2009
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update tutorial.
R=rsc CC=golang-dev
https://golang.org/cl/179063
parent
1c729599
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
421 additions
and
386 deletions
+421
-386
doc/go_tutorial.html
doc/go_tutorial.html
+184
-167
doc/go_tutorial.txt
doc/go_tutorial.txt
+30
-18
doc/progs/cat.go
doc/progs/cat.go
+17
-17
doc/progs/cat_rot13.go
doc/progs/cat_rot13.go
+23
-23
doc/progs/echo.go
doc/progs/echo.go
+8
-8
doc/progs/file.go
doc/progs/file.go
+16
-16
doc/progs/helloworld.go
doc/progs/helloworld.go
+1
-1
doc/progs/helloworld3.go
doc/progs/helloworld3.go
+8
-8
doc/progs/print.go
doc/progs/print.go
+11
-8
doc/progs/print_string.go
doc/progs/print_string.go
+5
-2
doc/progs/server.go
doc/progs/server.go
+19
-19
doc/progs/server1.go
doc/progs/server1.go
+20
-20
doc/progs/sieve.go
doc/progs/sieve.go
+7
-7
doc/progs/sieve1.go
doc/progs/sieve1.go
+15
-15
doc/progs/sort.go
doc/progs/sort.go
+22
-22
doc/progs/sortmain.go
doc/progs/sortmain.go
+28
-28
doc/progs/strings.go
doc/progs/strings.go
+4
-4
doc/progs/sum.go
doc/progs/sum.go
+3
-3
No files found.
doc/go_tutorial.html
View file @
34356e9a
...
@@ -30,7 +30,7 @@ Let's start in the usual way:
...
@@ -30,7 +30,7 @@ Let's start in the usual way:
07 import fmt
"
fmt
"
// Package implementing formatted I/O.
07 import fmt
"
fmt
"
// Package implementing formatted I/O.
<p>
<p>
09 func main() {
09 func main() {
10 fmt.Printf(
"
Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n
"
)
;
10 fmt.Printf(
"
Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n
"
)
11 }
11 }
</pre>
</pre>
<p>
<p>
...
@@ -55,6 +55,32 @@ The comment convention is the same as in C++:
...
@@ -55,6 +55,32 @@ The comment convention is the same as in C++:
<p>
<p>
Later we'll have much more to say about printing.
Later we'll have much more to say about printing.
<p>
<p>
<h2>
Semicolons
</h2>
<p>
You might have noticed that our program has no semicolons. In Go
code, the only place you typically see semicolons is separating the
clauses of
<code>
for
</code>
loops and the like; they are not necessary after
every statement.
<p>
In fact, what happens is that the formal language uses semicolons,
much as in C or Java, but they are inserted automatically
at the end of every line that looks like the end of a statement. You
don't need to type them yourself.
<p>
For details about how this is done you can see the language
specification, but in practice all you need to know is that you
never need to put a semicolon at the end of a line. (You can put
them in if you want to write multiple statements per line.) As an
extra help, you can also leave out a semicolon immediately before
a closing brace.
<p>
This approach makes for clean-looking, semicolon-free code. The
one surprise is that it's important to put the opening
brace of a construct such as an
<code>
if
</code>
statement on the same line as
the
<code>
if
</code>
; if you don't, there are situations that may not compile
or may give the wrong result. The language forces the brace style
to some extent.
<p>
<h2>
Compiling
</h2>
<h2>
Compiling
</h2>
<p>
<p>
Go is a compiled language. At the moment there are two compilers.
Go is a compiled language. At the moment there are two compilers.
...
@@ -92,30 +118,30 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
...
@@ -92,30 +118,30 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
05 package main
05 package main
<p>
<p>
07 import (
07 import (
08
"
os
"
;
08
"
os
"
09
"
flag
"
;
// command line option parser
09
"
flag
"
// command line option parser
10 )
10 )
<p>
<p>
12 var omitNewline = flag.Bool(
"
n
"
, false,
"
don't print final newline
"
)
12 var omitNewline = flag.Bool(
"
n
"
, false,
"
don't print final newline
"
)
<p>
<p>
14 const (
14 const (
15 Space =
"
"
;
15 Space =
"
"
16 Newline =
"
\n
"
;
16 Newline =
"
\n
"
17 )
17 )
<p>
<p>
19 func main() {
19 func main() {
20 flag.Parse()
;
// Scans the arg list and sets up flags
20 flag.Parse() // Scans the arg list and sets up flags
21 var s string =
""
;
21 var s string =
""
22 for i := 0; i
<
flag.NArg(); i++ {
22 for i := 0; i
<
flag.NArg(); i++ {
23 if i
>
0 {
23 if i
>
0 {
24 s += Space
24 s += Space
25 }
25 }
26 s += flag.Arg(i)
;
26 s += flag.Arg(i)
27 }
27 }
28 if !*omitNewline {
28 if !*omitNewline {
29 s += Newline
29 s += Newline
30 }
30 }
31 os.Stdout.WriteString(s)
;
31 os.Stdout.WriteString(s)
32 }
32 }
</pre>
</pre>
<p>
<p>
...
@@ -123,7 +149,7 @@ This program is small but it's doing a number of new things. In the last exampl
...
@@ -123,7 +149,7 @@ This program is small but it's doing a number of new things. In the last exampl
we saw
<code>
func
</code>
introduce a function. The keywords
<code>
var
</code>
,
<code>
const
</code>
, and
<code>
type
</code>
we saw
<code>
func
</code>
introduce a function. The keywords
<code>
var
</code>
,
<code>
const
</code>
, and
<code>
type
</code>
(not used yet) also introduce declarations, as does
<code>
import
</code>
.
(not used yet) also introduce declarations, as does
<code>
import
</code>
.
Notice that we can group declarations of the same sort into
Notice that we can group declarations of the same sort into
parenthesized
, semicolon-separated lists if we want
, as on lines 7-10 and 14-17.
parenthesized
lists, one item per line
, as on lines 7-10 and 14-17.
But it's not necessary to do so; we could have said
But it's not necessary to do so; we could have said
<p>
<p>
<pre>
<pre>
...
@@ -131,21 +157,6 @@ But it's not necessary to do so; we could have said
...
@@ -131,21 +157,6 @@ But it's not necessary to do so; we could have said
const Newline = "\n"
const Newline = "\n"
</pre>
</pre>
<p>
<p>
Semicolons aren't needed here; in fact, semicolons are unnecessary after any
top-level declaration, although they are needed as separators
<i>
within
</i>
a parenthesized list of declarations.
<p>
You can use semicolons just the way you would in C, C++, or Java, but if you
prefer you can also leave them out in many cases. They
<i>
separate
</i>
statements
rather than terminate them, so they aren't needed (but are still OK) at the end of the last
statement in a block.
They're also optional after braces, as in C.
Have a look at the source to
<code>
echo
</code>
.
The only necessary semicolons in that program are on lines 8, 15, and 21
and of course between the elements of the
<code>
for
</code>
loop on line 22.
The ones on line 9, 16, 26, and 31 are optional but are there because a semicolon
on the end of a list of statements makes it easier to edit the list later.
<p>
This program imports the
<code>
"
os
"
</code>
package to access its
<code>
Stdout
</code>
variable, of type
This program imports the
<code>
"
os
"
</code>
package to access its
<code>
Stdout
</code>
variable, of type
<code>
*os.File
</code>
. The
<code>
import
</code>
statement is actually a declaration: in its general form,
<code>
*os.File
</code>
. The
<code>
import
</code>
statement is actually a declaration: in its general form,
as used in our ``hello world'' program,
as used in our ``hello world'' program,
...
@@ -242,11 +253,11 @@ of course you can change a string <i>variable</i> simply by
...
@@ -242,11 +253,11 @@ of course you can change a string <i>variable</i> simply by
reassigning it. This snippet from
<code>
strings.go
</code>
is legal code:
reassigning it. This snippet from
<code>
strings.go
</code>
is legal code:
<p>
<p>
<pre>
<!-- progs/strings.go /hello/ /ciao/ -->
<pre>
<!-- progs/strings.go /hello/ /ciao/ -->
11 s :=
"
hello
"
;
11 s :=
"
hello
"
12 if s[1] != 'e' { os.Exit(1) }
12 if s[1] != 'e' { os.Exit(1) }
13 s =
"
good bye
"
;
13 s =
"
good bye
"
14 var p *string =
&
s
;
14 var p *string =
&
s
15 *p =
"
ciao
"
;
15 *p =
"
ciao
"
</pre>
</pre>
<p>
<p>
However the following statements are illegal because they would modify
However the following statements are illegal because they would modify
...
@@ -302,7 +313,7 @@ Using slices one can write this function (from <code>sum.go</code>):
...
@@ -302,7 +313,7 @@ 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]
13 }
13 }
...
@@ -313,7 +324,7 @@ Using slices one can write this function (from <code>sum.go</code>):
...
@@ -313,7 +324,7 @@ Using slices one can write this function (from <code>sum.go</code>):
and invoke it like this:
and invoke it like this:
<p>
<p>
<pre>
<!-- progs/sum.go /1,2,3/ -->
<pre>
<!-- progs/sum.go /1,2,3/ -->
19 s := sum(
&
[3]int{1,2,3})
;
// a slice of the array is passed to sum
19 s := sum(
&
[3]int{1,2,3}) // a slice of the array is passed to sum
</pre>
</pre>
<p>
<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
...
@@ -454,13 +465,13 @@ sort of open/close/read/write interface. Here's the start of <code>file.go</cod
...
@@ -454,13 +465,13 @@ sort of open/close/read/write interface. Here's the start of <code>file.go</cod
05 package file
05 package file
<p>
<p>
07 import (
07 import (
08
"
os
"
;
08
"
os
"
09
"
syscall
"
;
09
"
syscall
"
10 )
10 )
<p>
<p>
12 type File struct {
12 type File struct {
13 fd int
;
// file descriptor number
13 fd int // file descriptor number
14 name string
;
// file name at Open time
14 name string // file name at Open time
15 }
15 }
</pre>
</pre>
<p>
<p>
...
@@ -520,9 +531,9 @@ We can use the factory to construct some familiar, exported variables of type <c
...
@@ -520,9 +531,9 @@ We can use the factory to construct some familiar, exported variables of type <c
<p>
<p>
<pre>
<!-- progs/file.go /var/ /^.$/ -->
<pre>
<!-- progs/file.go /var/ /^.$/ -->
24 var (
24 var (
25 Stdin = newFile(0,
"
/dev/stdin
"
)
;
25 Stdin = newFile(0,
"
/dev/stdin
"
)
26 Stdout = newFile(1,
"
/dev/stdout
"
)
;
26 Stdout = newFile(1,
"
/dev/stdout
"
)
27 Stderr = newFile(2,
"
/dev/stderr
"
)
;
27 Stderr = newFile(2,
"
/dev/stderr
"
)
28 )
28 )
</pre>
</pre>
<p>
<p>
...
@@ -531,9 +542,9 @@ exported factory to use is <code>Open</code>:
...
@@ -531,9 +542,9 @@ exported factory to use is <code>Open</code>:
<p>
<p>
<pre>
<!-- progs/file.go /func.Open/ /^}/ -->
<pre>
<!-- progs/file.go /func.Open/ /^}/ -->
30 func Open(name string, mode int, perm int) (file *File, err os.Error) {
30 func Open(name string, mode int, perm int) (file *File, err os.Error) {
31 r, e := syscall.Open(name, mode, perm)
;
31 r, e := syscall.Open(name, mode, perm)
32 if e != 0 {
32 if e != 0 {
33 err = os.Errno(e)
;
33 err = os.Errno(e)
34 }
34 }
35 return newFile(r, name), err
35 return newFile(r, name), err
36 }
36 }
...
@@ -569,10 +580,10 @@ each of which declares a receiver variable <code>file</code>.
...
@@ -569,10 +580,10 @@ each of which declares a receiver variable <code>file</code>.
39 if file == nil {
39 if file == nil {
40 return os.EINVAL
40 return os.EINVAL
41 }
41 }
42 e := syscall.Close(file.fd)
;
42 e := syscall.Close(file.fd)
43 file.fd = -1
;
// so it can't be closed again
43 file.fd = -1 // so it can't be closed again
44 if e != 0 {
44 if e != 0 {
45 return os.Errno(e)
;
45 return os.Errno(e)
46 }
46 }
47 return nil
47 return nil
48 }
48 }
...
@@ -581,9 +592,9 @@ each of which declares a receiver variable <code>file</code>.
...
@@ -581,9 +592,9 @@ each of which declares a receiver variable <code>file</code>.
51 if file == nil {
51 if file == nil {
52 return -1, os.EINVAL
52 return -1, os.EINVAL
53 }
53 }
54 r, e := syscall.Read(file.fd, b)
;
54 r, e := syscall.Read(file.fd, b)
55 if e != 0 {
55 if e != 0 {
56 err = os.Errno(e)
;
56 err = os.Errno(e)
57 }
57 }
58 return int(r), err
58 return int(r), err
59 }
59 }
...
@@ -592,9 +603,9 @@ each of which declares a receiver variable <code>file</code>.
...
@@ -592,9 +603,9 @@ each of which declares a receiver variable <code>file</code>.
62 if file == nil {
62 if file == nil {
63 return -1, os.EINVAL
63 return -1, os.EINVAL
64 }
64 }
65 r, e := syscall.Write(file.fd, b)
;
65 r, e := syscall.Write(file.fd, b)
66 if e != 0 {
66 if e != 0 {
67 err = os.Errno(e)
;
67 err = os.Errno(e)
68 }
68 }
69 return int(r), err
69 return int(r), err
70 }
70 }
...
@@ -623,18 +634,18 @@ We can now use our new package:
...
@@ -623,18 +634,18 @@ We can now use our new package:
05 package main
05 package main
<p>
<p>
07 import (
07 import (
08
"
./file
"
;
08
"
./file
"
09
"
fmt
"
;
09
"
fmt
"
10
"
os
"
;
10
"
os
"
11 )
11 )
<p>
<p>
13 func main() {
13 func main() {
14 hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}
;
14 hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}
15 file.Stdout.Write(hello)
;
15 file.Stdout.Write(hello)
16 file, err := file.Open(
"
/does/not/exist
"
, 0, 0)
;
16 file, err := file.Open(
"
/does/not/exist
"
, 0, 0)
17 if file == nil {
17 if file == nil {
18 fmt.Printf(
"
can't open file; err=%s\n
"
, err.String())
;
18 fmt.Printf(
"
can't open file; err=%s\n
"
, err.String())
19 os.Exit(1)
;
19 os.Exit(1)
20 }
20 }
21 }
21 }
</pre>
</pre>
...
@@ -660,43 +671,43 @@ Building on the <code>file</code> package, here's a simple version of the Unix u
...
@@ -660,43 +671,43 @@ Building on the <code>file</code> package, here's a simple version of the Unix u
05 package main
05 package main
<p>
<p>
07 import (
07 import (
08
"
./file
"
;
08
"
./file
"
09
"
flag
"
;
09
"
flag
"
10
"
fmt
"
;
10
"
fmt
"
11
"
os
"
;
11
"
os
"
12 )
12 )
<p>
<p>
14 func cat(f *file.File) {
14 func cat(f *file.File) {
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)
22 case nr == 0: // EOF
22 case nr == 0: // EOF
23 return
;
23 return
24 case nr
>
0:
24 case nr
>
0:
25 if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
25 if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
26 fmt.Fprintf(os.Stderr,
"
cat: error writing from %s: %s\n
"
, f.String(), ew.String())
;
26 fmt.Fprintf(os.Stderr,
"
cat: error writing from %s: %s\n
"
, f.String(), ew.String())
27 }
27 }
28 }
28 }
29 }
29 }
30 }
30 }
<p>
<p>
32 func main() {
32 func main() {
33 flag.Parse()
;
// Scans the arg list and sets up flags
33 flag.Parse() // Scans the arg list and sets up flags
34 if flag.NArg() == 0 {
34 if flag.NArg() == 0 {
35 cat(file.Stdin)
;
35 cat(file.Stdin)
36 }
36 }
37 for i := 0; i
<
flag.NArg(); i++ {
37 for i := 0; i
<
flag.NArg(); i++ {
38 f, err := file.Open(flag.Arg(i), 0, 0)
;
38 f, err := file.Open(flag.Arg(i), 0, 0)
39 if f == nil {
39 if f == nil {
40 fmt.Fprintf(os.Stderr,
"
cat: can't open %s: error %s\n
"
, flag.Arg(i), err)
;
40 fmt.Fprintf(os.Stderr,
"
cat: can't open %s: error %s\n
"
, flag.Arg(i), err)
41 os.Exit(1)
;
41 os.Exit(1)
42 }
42 }
43 cat(f)
;
43 cat(f)
44 f.Close()
;
44 f.Close()
45 }
45 }
46 }
46 }
</pre>
</pre>
...
@@ -729,8 +740,8 @@ Here is code from <code>progs/cat_rot13.go</code>:
...
@@ -729,8 +740,8 @@ Here is code from <code>progs/cat_rot13.go</code>:
<p>
<p>
<pre>
<!-- progs/cat_rot13.go /type.reader/ /^}/ -->
<pre>
<!-- progs/cat_rot13.go /type.reader/ /^}/ -->
26 type reader interface {
26 type reader interface {
27 Read(b []byte) (ret int, err os.Error)
;
27 Read(b []byte) (ret int, err os.Error)
28 String() string
;
28 String() string
29 }
29 }
</pre>
</pre>
<p>
<p>
...
@@ -746,7 +757,7 @@ we have a second implementation of the <code>reader</code> interface.
...
@@ -746,7 +757,7 @@ we have a second implementation of the <code>reader</code> interface.
<p>
<p>
<pre>
<!-- progs/cat_rot13.go /type.rotate13/ /end.of.rotate13/ -->
<pre>
<!-- progs/cat_rot13.go /type.rotate13/ /end.of.rotate13/ -->
31 type rotate13 struct {
31 type rotate13 struct {
32 source reader
;
32 source reader
33 }
33 }
<p>
<p>
35 func newRotate13(source reader) *rotate13 {
35 func newRotate13(source reader) *rotate13 {
...
@@ -754,7 +765,7 @@ we have a second implementation of the <code>reader</code> interface.
...
@@ -754,7 +765,7 @@ we have a second implementation of the <code>reader</code> interface.
37 }
37 }
<p>
<p>
39 func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
39 func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
40 r, e := r13.source.Read(b)
;
40 r, e := r13.source.Read(b)
41 for i := 0; i
<
r; i++ {
41 for i := 0; i
<
r; i++ {
42 b[i] = rot13(b[i])
42 b[i] = rot13(b[i])
43 }
43 }
...
@@ -779,8 +790,8 @@ and use it from within a mostly unchanged <code>cat()</code> function:
...
@@ -779,8 +790,8 @@ and use it from within a mostly unchanged <code>cat()</code> function:
<p>
<p>
<pre>
<!-- progs/cat_rot13.go /func.cat/ /^}/ -->
<pre>
<!-- progs/cat_rot13.go /func.cat/ /^}/ -->
52 func cat(r reader) {
52 func cat(r reader) {
53 const NBUF = 512
;
53 const NBUF = 512
54 var buf [NBUF]byte
;
54 var buf [NBUF]byte
<p>
<p>
56 if *rot13Flag {
56 if *rot13Flag {
57 r = newRotate13(r)
57 r = newRotate13(r)
...
@@ -788,14 +799,14 @@ and use it from within a mostly unchanged <code>cat()</code> function:
...
@@ -788,14 +799,14 @@ and use it from within a mostly unchanged <code>cat()</code> function:
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)
64 case nr == 0: // EOF
64 case nr == 0: // EOF
65 return
;
65 return
66 case nr
>
0:
66 case nr
>
0:
67 nw, ew := file.Stdout.Write(buf[0:nr])
;
67 nw, ew := file.Stdout.Write(buf[0:nr])
68 if nw != nr {
68 if nw != nr {
69 fmt.Fprintf(os.Stderr,
"
cat: error writing from %s: %s\n
"
, r.String(), ew.String())
;
69 fmt.Fprintf(os.Stderr,
"
cat: error writing from %s: %s\n
"
, r.String(), ew.String())
70 }
70 }
71 }
71 }
72 }
72 }
...
@@ -851,7 +862,7 @@ As an example, consider this simple sort algorithm taken from <code>progs/sort.g
...
@@ -851,7 +862,7 @@ As an example, consider this simple sort algorithm taken from <code>progs/sort.g
13 func Sort(data Interface) {
13 func Sort(data Interface) {
14 for i := 1; i
<
data.Len(); i++ {
14 for i := 1; i
<
data.Len(); i++ {
15 for j := i; j
>
0
&&
data.Less(j, j-1); j-- {
15 for j := i; j
>
0
&&
data.Less(j, j-1); j-- {
16 data.Swap(j, j-1)
;
16 data.Swap(j, j-1)
17 }
17 }
18 }
18 }
19 }
19 }
...
@@ -861,9 +872,9 @@ The code needs only three methods, which we wrap into sort's <code>Interface</co
...
@@ -861,9 +872,9 @@ The code needs only three methods, which we wrap into sort's <code>Interface</co
<p>
<p>
<pre>
<!-- progs/sort.go /interface/ /^}/ -->
<pre>
<!-- progs/sort.go /interface/ /^}/ -->
07 type Interface interface {
07 type Interface interface {
08 Len() int
;
08 Len() int
09 Less(i, j int) bool
;
09 Less(i, j int) bool
10 Swap(i, j int)
;
10 Swap(i, j int)
11 }
11 }
</pre>
</pre>
<p>
<p>
...
@@ -874,9 +885,9 @@ arrays of integers, strings, etc.; here's the code for arrays of <code>int</code
...
@@ -874,9 +885,9 @@ arrays of integers, strings, etc.; here's the code for arrays of <code>int</code
<pre>
<!-- progs/sort.go /type.*IntArray/ /Swap/ -->
<pre>
<!-- progs/sort.go /type.*IntArray/ /Swap/ -->
33 type IntArray []int
33 type IntArray []int
<p>
<p>
35 func (p IntArray) Len() int { return len(p)
;
}
35 func (p IntArray) Len() int { return len(p) }
36 func (p IntArray) Less(i, j int) bool { return p[i]
<
p[j]
;
}
36 func (p IntArray) Less(i, j int) bool { return p[i]
<
p[j] }
37 func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]
;
}
37 func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
</pre>
</pre>
<p>
<p>
Here we see methods defined for non-
<code>
struct
</code>
types. You can define methods
Here we see methods defined for non-
<code>
struct
</code>
types. You can define methods
...
@@ -888,9 +899,9 @@ to test that the result is sorted.
...
@@ -888,9 +899,9 @@ to test that the result is sorted.
<p>
<p>
<pre>
<!-- progs/sortmain.go /func.ints/ /^}/ -->
<pre>
<!-- progs/sortmain.go /func.ints/ /^}/ -->
12 func ints() {
12 func ints() {
13 data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
;
13 data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
14 a := sort.IntArray(data)
;
14 a := sort.IntArray(data)
15 sort.Sort(a)
;
15 sort.Sort(a)
16 if !sort.IsSorted(a) {
16 if !sort.IsSorted(a) {
17 panic()
17 panic()
18 }
18 }
...
@@ -902,18 +913,18 @@ to implement the three methods for that type, like this:
...
@@ -902,18 +913,18 @@ to implement the three methods for that type, like this:
<p>
<p>
<pre>
<!-- progs/sortmain.go /type.day/ /Swap/ -->
<pre>
<!-- progs/sortmain.go /type.day/ /Swap/ -->
30 type day struct {
30 type day struct {
31 num int
;
31 num int
32 shortName string
;
32 shortName string
33 longName string
;
33 longName string
34 }
34 }
<p>
<p>
36 type dayArray struct {
36 type dayArray struct {
37 data []*day
;
37 data []*day
38 }
38 }
<p>
<p>
40 func (p *dayArray) Len() int { return len(p.data)
;
}
40 func (p *dayArray) Len() int { return len(p.data) }
41 func (p *dayArray) Less(i, j int) bool { return p.data[i].num
<
p.data[j].num
;
}
41 func (p *dayArray) Less(i, j int) bool { return p.data[i].num
<
p.data[j].num }
42 func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i]
;
}
42 func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] }
</pre>
</pre>
<p>
<p>
<p>
<p>
...
@@ -944,8 +955,8 @@ can just say <code>%d</code>; <code>Printf</code> knows the size and signedness
...
@@ -944,8 +955,8 @@ can just say <code>%d</code>; <code>Printf</code> knows the size and signedness
integer and can do the right thing for you. The snippet
integer and can do the right thing for you. The snippet
<p>
<p>
<pre>
<!-- progs/print.go NR==10 NR==11 -->
<pre>
<!-- progs/print.go NR==10 NR==11 -->
10 var u64 uint64 = 1
<<
64-1
;
10 var u64 uint64 = 1
<<
64-1
11 fmt.Printf(
"
%d %d\n
"
, u64, int64(u64))
;
11 fmt.Printf(
"
%d %d\n
"
, u64, int64(u64))
</pre>
</pre>
<p>
<p>
prints
prints
...
@@ -957,11 +968,14 @@ prints
...
@@ -957,11 +968,14 @@ prints
In fact, if you're lazy the format
<code>
%v
</code>
will print, in a simple
In fact, if you're lazy the format
<code>
%v
</code>
will print, in a simple
appropriate style, any value, even an array or structure. The output of
appropriate style, any value, even an array or structure. The output of
<p>
<p>
<pre>
<!-- progs/print.go NR==14 NR==17 -->
<pre>
<!-- progs/print.go NR==14 NR==20 -->
14 type T struct { a int; b string };
14 type T struct {
15 t := T{77,
"
Sunset Strip
"
};
15 a int
16 a := []int{1, 2, 3, 4};
16 b string
17 fmt.Printf(
"
%v %v %v\n
"
, u64, t, a);
17 }
18 t := T{77,
"
Sunset Strip
"
}
19 a := []int{1, 2, 3, 4}
20 fmt.Printf(
"
%v %v %v\n
"
, u64, t, a)
</pre>
</pre>
<p>
<p>
is
is
...
@@ -977,9 +991,9 @@ of <code>%v</code> while <code>Println</code> inserts spaces between arguments
...
@@ -977,9 +991,9 @@ of <code>%v</code> while <code>Println</code> inserts spaces between arguments
and adds a newline. The output of each of these two lines is identical
and adds a newline. The output of each of these two lines is identical
to that of the
<code>
Printf
</code>
call above.
to that of the
<code>
Printf
</code>
call above.
<p>
<p>
<pre>
<!-- progs/print.go NR==
18 NR==19
-->
<pre>
<!-- progs/print.go NR==
21 NR==22
-->
18 fmt.Print(u64,
"
"
, t,
"
"
, a,
"
\n
"
);
21 fmt.Print(u64,
"
"
, t,
"
"
, a,
"
\n
"
)
19 fmt.Println(u64, t, a);
22 fmt.Println(u64, t, a)
</pre>
</pre>
<p>
<p>
If you have your own type you'd like
<code>
Printf
</code>
or
<code>
Print
</code>
to format,
If you have your own type you'd like
<code>
Printf
</code>
or
<code>
Print
</code>
to format,
...
@@ -989,16 +1003,19 @@ the method and if so, use it rather than some other formatting.
...
@@ -989,16 +1003,19 @@ the method and if so, use it rather than some other formatting.
Here's a simple example.
Here's a simple example.
<p>
<p>
<pre>
<!-- progs/print_string.go NR==9 END -->
<pre>
<!-- progs/print_string.go NR==9 END -->
09 type testType struct { a int; b string }
09 type testType struct {
10 a int
11 b string
12 }
<p>
<p>
1
1
func (t *testType) String() string {
1
4
func (t *testType) String() string {
1
2
return fmt.Sprint(t.a) +
"
"
+ t.b
1
5
return fmt.Sprint(t.a) +
"
"
+ t.b
1
3
}
1
6
}
<p>
<p>
1
5
func main() {
1
8
func main() {
1
6 t :=
&
testType{77,
"
Sunset Strip
"
};
1
9 t :=
&
testType{77,
"
Sunset Strip
"
}
17
fmt.Println(t)
20
fmt.Println(t)
18
}
21
}
</pre>
</pre>
<p>
<p>
Since
<code>
*testType
</code>
has a
<code>
String()
</code>
method, the
Since
<code>
*testType
</code>
has a
<code>
String()
</code>
method, the
...
@@ -1128,7 +1145,7 @@ operator <code><-</code> (receive) retrieves the next value on the channel.
...
@@ -1128,7 +1145,7 @@ operator <code><-</code> (receive) retrieves the next value on the channel.
17 // removing those divisible by 'prime'.
17 // removing those divisible by 'prime'.
18 func filter(in, out chan int, prime int) {
18 func filter(in, out chan int, prime int) {
19 for {
19 for {
20 i :=
<
-in
;
// Receive value of new variable 'i' from 'in'.
20 i :=
<
-in // Receive value of new variable 'i' from 'in'.
21 if i % prime != 0 {
21 if i % prime != 0 {
22 out
<
- i // Send 'i' to channel 'out'.
22 out
<
- i // Send 'i' to channel 'out'.
23 }
23 }
...
@@ -1163,13 +1180,13 @@ together:
...
@@ -1163,13 +1180,13 @@ together:
<p>
<p>
<pre>
<!-- progs/sieve.go /func.main/ /^}/ -->
<pre>
<!-- progs/sieve.go /func.main/ /^}/ -->
28 func main() {
28 func main() {
29 ch := make(chan int)
;
// Create a new channel.
29 ch := make(chan int) // Create a new channel.
30 go generate(ch)
;
// Start generate() as a goroutine.
30 go generate(ch) // Start generate() as a goroutine.
31 for {
31 for {
32 prime :=
<
-ch
;
32 prime :=
<
-ch
33 fmt.Println(prime)
;
33 fmt.Println(prime)
34 ch1 := make(chan int)
;
34 ch1 := make(chan int)
35 go filter(ch, ch1, prime)
;
35 go filter(ch, ch1, prime)
36 ch = ch1
36 ch = ch1
37 }
37 }
38 }
38 }
...
@@ -1186,13 +1203,13 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
...
@@ -1186,13 +1203,13 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
<p>
<p>
<pre>
<!-- progs/sieve1.go /func.generate/ /^}/ -->
<pre>
<!-- progs/sieve1.go /func.generate/ /^}/ -->
10 func generate() chan int {
10 func generate() chan int {
11 ch := make(chan int)
;
11 ch := make(chan int)
12 go func(){
12 go func(){
13 for i := 2; ; i++ {
13 for i := 2; ; i++ {
14 ch
<
- i
14 ch
<
- i
15 }
15 }
16 }()
;
16 }()
17 return ch
;
17 return ch
18 }
18 }
</pre>
</pre>
<p>
<p>
...
@@ -1210,15 +1227,15 @@ The same change can be made to <code>filter</code>:
...
@@ -1210,15 +1227,15 @@ The same change can be made to <code>filter</code>:
<p>
<p>
<pre>
<!-- progs/sieve1.go /func.filter/ /^}/ -->
<pre>
<!-- progs/sieve1.go /func.filter/ /^}/ -->
21 func filter(in chan int, prime int) chan int {
21 func filter(in chan int, prime int) chan int {
22 out := make(chan int)
;
22 out := make(chan int)
23 go func() {
23 go func() {
24 for {
24 for {
25 if i :=
<
-in; i % prime != 0 {
25 if i :=
<
-in; i % prime != 0 {
26 out
<
- i
26 out
<
- i
27 }
27 }
28 }
28 }
29 }()
;
29 }()
30 return out
;
30 return out
31 }
31 }
</pre>
</pre>
<p>
<p>
...
@@ -1227,16 +1244,16 @@ result, and while we're at it let's turn it into a factory too:
...
@@ -1227,16 +1244,16 @@ result, and while we're at it let's turn it into a factory too:
<p>
<p>
<pre>
<!-- progs/sieve1.go /func.sieve/ /^}/ -->
<pre>
<!-- progs/sieve1.go /func.sieve/ /^}/ -->
33 func sieve() chan int {
33 func sieve() chan int {
34 out := make(chan int)
;
34 out := make(chan int)
35 go func() {
35 go func() {
36 ch := generate()
;
36 ch := generate()
37 for {
37 for {
38 prime :=
<
-ch
;
38 prime :=
<
-ch
39 out
<
- prime
;
39 out
<
- prime
40 ch = filter(ch, prime)
;
40 ch = filter(ch, prime)
41 }
41 }
42 }()
;
42 }()
43 return out
;
43 return out
44 }
44 }
</pre>
</pre>
<p>
<p>
...
@@ -1244,9 +1261,9 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
...
@@ -1244,9 +1261,9 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
<p>
<p>
<pre>
<!-- progs/sieve1.go /func.main/ /^}/ -->
<pre>
<!-- progs/sieve1.go /func.main/ /^}/ -->
46 func main() {
46 func main() {
47 primes := sieve()
;
47 primes := sieve()
48 for {
48 for {
49 fmt.Println(
<
-primes)
;
49 fmt.Println(
<
-primes)
50 }
50 }
51 }
51 }
</pre>
</pre>
...
@@ -1262,8 +1279,8 @@ that will be used for the reply.
...
@@ -1262,8 +1279,8 @@ that will be used for the reply.
<p>
<p>
<pre>
<!-- progs/server.go /type.request/ /^}/ -->
<pre>
<!-- progs/server.go /type.request/ /^}/ -->
09 type request struct {
09 type request struct {
10 a, b int
;
10 a, b int
11 replyc chan int
;
11 replyc chan int
12 }
12 }
</pre>
</pre>
<p>
<p>
...
@@ -1274,8 +1291,8 @@ code that invokes the operation and responds to the request:
...
@@ -1274,8 +1291,8 @@ code that invokes the operation and responds to the request:
14 type binOp func(a, b int) int
14 type binOp func(a, b int) int
<p>
<p>
16 func run(op binOp, req *request) {
16 func run(op binOp, req *request) {
17 reply := op(req.a, req.b)
;
17 reply := op(req.a, req.b)
18 req.replyc
<
- reply
;
18 req.replyc
<
- reply
19 }
19 }
</pre>
</pre>
<p>
<p>
...
@@ -1288,8 +1305,8 @@ a long-running operation, starting a goroutine to do the actual work.
...
@@ -1288,8 +1305,8 @@ a long-running operation, starting a goroutine to do the actual work.
<pre>
<!-- progs/server.go /func.server/ /^}/ -->
<pre>
<!-- progs/server.go /func.server/ /^}/ -->
21 func server(op binOp, service chan *request) {
21 func server(op binOp, service chan *request) {
22 for {
22 for {
23 req :=
<
-service
;
23 req :=
<
-service
24 go run(op, req)
;
// don't wait for it
24 go run(op, req) // don't wait for it
25 }
25 }
26 }
26 }
</pre>
</pre>
...
@@ -1299,9 +1316,9 @@ connected to it:
...
@@ -1299,9 +1316,9 @@ connected to it:
<p>
<p>
<pre>
<!-- progs/server.go /func.startServer/ /^}/ -->
<pre>
<!-- progs/server.go /func.startServer/ /^}/ -->
28 func startServer(op binOp) chan *request {
28 func startServer(op binOp) chan *request {
29 req := make(chan *request)
;
29 req := make(chan *request)
30 go server(op, req)
;
30 go server(op, req)
31 return req
;
31 return req
32 }
32 }
</pre>
</pre>
<p>
<p>
...
@@ -1311,22 +1328,22 @@ does it check the results.
...
@@ -1311,22 +1328,22 @@ does it check the results.
<p>
<p>
<pre>
<!-- progs/server.go /func.main/ /^}/ -->
<pre>
<!-- progs/server.go /func.main/ /^}/ -->
34 func main() {
34 func main() {
35 adder := startServer(func(a, b int) int { return a + b })
;
35 adder := startServer(func(a, b int) int { return a + b })
36 const N = 100
;
36 const N = 100
37 var reqs [N]request
;
37 var reqs [N]request
38 for i := 0; i
<
N; i++ {
38 for i := 0; i
<
N; i++ {
39 req :=
&
reqs[i]
;
39 req :=
&
reqs[i]
40 req.a = i
;
40 req.a = i
41 req.b = i + N
;
41 req.b = i + N
42 req.replyc = make(chan int)
;
42 req.replyc = make(chan int)
43 adder
<
- req
;
43 adder
<
- req
44 }
44 }
45 for i := N-1; i
>
= 0; i-- { // doesn't matter what order
45 for i := N-1; i
>
= 0; i-- { // doesn't matter what order
46 if
<
-reqs[i].replyc != N + 2*i {
46 if
<
-reqs[i].replyc != N + 2*i {
47 fmt.Println(
"
fail at
"
, i)
;
47 fmt.Println(
"
fail at
"
, i)
48 }
48 }
49 }
49 }
50 fmt.Println(
"
done
"
)
;
50 fmt.Println(
"
done
"
)
51 }
51 }
</pre>
</pre>
<p>
<p>
...
@@ -1336,10 +1353,10 @@ we can provide a second, <code>quit</code> channel to the server:
...
@@ -1336,10 +1353,10 @@ we can provide a second, <code>quit</code> channel to the server:
<p>
<p>
<pre>
<!-- progs/server1.go /func.startServer/ /^}/ -->
<pre>
<!-- progs/server1.go /func.startServer/ /^}/ -->
32 func startServer(op binOp) (service chan *request, quit chan bool) {
32 func startServer(op binOp) (service chan *request, quit chan bool) {
33 service = make(chan *request)
;
33 service = make(chan *request)
34 quit = make(chan bool)
;
34 quit = make(chan bool)
35 go server(op, service, quit)
;
35 go server(op, service, quit)
36 return service, quit
;
36 return service, quit
37 }
37 }
</pre>
</pre>
<p>
<p>
...
@@ -1350,9 +1367,9 @@ It passes the quit channel to the <code>server</code> function, which uses it li
...
@@ -1350,9 +1367,9 @@ It passes the quit channel to the <code>server</code> function, which uses it li
22 for {
22 for {
23 select {
23 select {
24 case req :=
<
-service:
24 case req :=
<
-service:
25 go run(op, req)
;
// don't wait for it
25 go run(op, req) // don't wait for it
26 case
<
-quit:
26 case
<
-quit:
27 return
;
27 return
28 }
28 }
29 }
29 }
30 }
30 }
...
@@ -1369,11 +1386,11 @@ All that's left is to strobe the <code>quit</code> channel
...
@@ -1369,11 +1386,11 @@ All that's left is to strobe the <code>quit</code> channel
at the end of main:
at the end of main:
<p>
<p>
<pre>
<!-- progs/server1.go /adder,.quit/ -->
<pre>
<!-- progs/server1.go /adder,.quit/ -->
40 adder, quit := startServer(func(a, b int) int { return a + b })
;
40 adder, quit := startServer(func(a, b int) int { return a + b })
</pre>
</pre>
...
...
<pre>
<!-- progs/server1.go /quit....true/ -->
<pre>
<!-- progs/server1.go /quit....true/ -->
55 quit
<
- true
;
55 quit
<
- true
</pre>
</pre>
<p>
<p>
There's a lot more to Go programming and concurrent programming in general but this
There's a lot more to Go programming and concurrent programming in general but this
...
...
doc/go_tutorial.txt
View file @
34356e9a
...
@@ -47,6 +47,33 @@ The comment convention is the same as in C++:
...
@@ -47,6 +47,33 @@ The comment convention is the same as in C++:
Later we'll have much more to say about printing.
Later we'll have much more to say about printing.
Semicolons
----
You might have noticed that our program has no semicolons. In Go
code, the only place you typically see semicolons is separating the
clauses of "for" loops and the like; they are not necessary after
every statement.
In fact, what happens is that the formal language uses semicolons,
much as in C or Java, but they are inserted automatically
at the end of every line that looks like the end of a statement. You
don't need to type them yourself.
For details about how this is done you can see the language
specification, but in practice all you need to know is that you
never need to put a semicolon at the end of a line. (You can put
them in if you want to write multiple statements per line.) As an
extra help, you can also leave out a semicolon immediately before
a closing brace.
This approach makes for clean-looking, semicolon-free code. The
one surprise is that it's important to put the opening
brace of a construct such as an "if" statement on the same line as
the "if"; if you don't, there are situations that may not compile
or may give the wrong result. The language forces the brace style
to some extent.
Compiling
Compiling
----
----
...
@@ -84,27 +111,12 @@ This program is small but it's doing a number of new things. In the last exampl
...
@@ -84,27 +111,12 @@ This program is small but it's doing a number of new things. In the last exampl
we saw "func" introduce a function. The keywords "var", "const", and "type"
we saw "func" introduce a function. The keywords "var", "const", and "type"
(not used yet) also introduce declarations, as does "import".
(not used yet) also introduce declarations, as does "import".
Notice that we can group declarations of the same sort into
Notice that we can group declarations of the same sort into
parenthesized
, semicolon-separated lists if we want
, as on lines 7-10 and 14-17.
parenthesized
lists, one item per line
, as on lines 7-10 and 14-17.
But it's not necessary to do so; we could have said
But it's not necessary to do so; we could have said
const Space = " "
const Space = " "
const Newline = "\n"
const Newline = "\n"
Semicolons aren't needed here; in fact, semicolons are unnecessary after any
top-level declaration, although they are needed as separators <i>within</i>
a parenthesized list of declarations.
You can use semicolons just the way you would in C, C++, or Java, but if you
prefer you can also leave them out in many cases. They <i>separate</i> statements
rather than terminate them, so they aren't needed (but are still OK) at the end of the last
statement in a block.
They're also optional after braces, as in C.
Have a look at the source to "echo".
The only necessary semicolons in that program are on lines 8, 15, and 21
and of course between the elements of the "for" loop on line 22.
The ones on line 9, 16, 26, and 31 are optional but are there because a semicolon
on the end of a list of statements makes it easier to edit the list later.
This program imports the ""os"" package to access its "Stdout" variable, of type
This program imports the ""os"" package to access its "Stdout" variable, of type
"*os.File". The "import" statement is actually a declaration: in its general form,
"*os.File". The "import" statement is actually a declaration: in its general form,
as used in our ``hello world'' program,
as used in our ``hello world'' program,
...
@@ -634,7 +646,7 @@ prints
...
@@ -634,7 +646,7 @@ prints
In fact, if you're lazy the format "%v" will print, in a simple
In fact, if you're lazy the format "%v" will print, in a simple
appropriate style, any value, even an array or structure. The output of
appropriate style, any value, even an array or structure. The output of
--PROG progs/print.go 'NR==14' 'NR==
17
'
--PROG progs/print.go 'NR==14' 'NR==
20
'
is
is
...
@@ -647,7 +659,7 @@ of "%v" while "Println" inserts spaces between arguments
...
@@ -647,7 +659,7 @@ of "%v" while "Println" inserts spaces between arguments
and adds a newline. The output of each of these two lines is identical
and adds a newline. The output of each of these two lines is identical
to that of the "Printf" call above.
to that of the "Printf" call above.
--PROG progs/print.go 'NR==
18' 'NR==19
'
--PROG progs/print.go 'NR==
21' 'NR==22
'
If you have your own type you'd like "Printf" or "Print" to format,
If you have your own type you'd like "Printf" or "Print" to format,
just give it a "String()" method that returns a string. The print
just give it a "String()" method that returns a string. The print
...
...
doc/progs/cat.go
View file @
34356e9a
...
@@ -5,42 +5,42 @@
...
@@ -5,42 +5,42 @@
package
main
package
main
import
(
import
(
"./file"
;
"./file"
"flag"
;
"flag"
"fmt"
;
"fmt"
"os"
;
"os"
)
)
func
cat
(
f
*
file
.
File
)
{
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
{
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: error writing from %s: %s
\n
"
,
f
.
String
(),
ew
.
String
())
;
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: error writing from %s: %s
\n
"
,
f
.
String
(),
ew
.
String
())
}
}
}
}
}
}
}
}
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
)
}
}
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
f
,
err
:=
file
.
Open
(
flag
.
Arg
(
i
),
0
,
0
)
;
f
,
err
:=
file
.
Open
(
flag
.
Arg
(
i
),
0
,
0
)
if
f
==
nil
{
if
f
==
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: can't open %s: error %s
\n
"
,
flag
.
Arg
(
i
),
err
)
;
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: can't open %s: error %s
\n
"
,
flag
.
Arg
(
i
),
err
)
os
.
Exit
(
1
)
;
os
.
Exit
(
1
)
}
}
cat
(
f
)
;
cat
(
f
)
f
.
Close
()
;
f
.
Close
()
}
}
}
}
doc/progs/cat_rot13.go
View file @
34356e9a
...
@@ -5,17 +5,17 @@
...
@@ -5,17 +5,17 @@
package
main
package
main
import
(
import
(
"./file"
;
"./file"
"flag"
;
"flag"
"fmt"
;
"fmt"
"os"
;
"os"
)
)
var
rot13Flag
=
flag
.
Bool
(
"rot13"
,
false
,
"rot13 the input"
)
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
...
@@ -24,12 +24,12 @@ func rot13(b byte) byte {
...
@@ -24,12 +24,12 @@ func rot13(b byte) byte {
}
}
type
reader
interface
{
type
reader
interface
{
Read
(
b
[]
byte
)
(
ret
int
,
err
os
.
Error
)
;
Read
(
b
[]
byte
)
(
ret
int
,
err
os
.
Error
)
String
()
string
;
String
()
string
}
}
type
rotate13
struct
{
type
rotate13
struct
{
source
reader
;
source
reader
}
}
func
newRotate13
(
source
reader
)
*
rotate13
{
func
newRotate13
(
source
reader
)
*
rotate13
{
...
@@ -37,7 +37,7 @@ func newRotate13(source reader) *rotate13 {
...
@@ -37,7 +37,7 @@ func newRotate13(source reader) *rotate13 {
}
}
func
(
r13
*
rotate13
)
Read
(
b
[]
byte
)
(
ret
int
,
err
os
.
Error
)
{
func
(
r13
*
rotate13
)
Read
(
b
[]
byte
)
(
ret
int
,
err
os
.
Error
)
{
r
,
e
:=
r13
.
source
.
Read
(
b
)
;
r
,
e
:=
r13
.
source
.
Read
(
b
)
for
i
:=
0
;
i
<
r
;
i
++
{
for
i
:=
0
;
i
<
r
;
i
++
{
b
[
i
]
=
rot13
(
b
[
i
])
b
[
i
]
=
rot13
(
b
[
i
])
}
}
...
@@ -50,8 +50,8 @@ func (r13 *rotate13) String() string {
...
@@ -50,8 +50,8 @@ func (r13 *rotate13) String() string {
// end of rotate13 implementation
// end of rotate13 implementation
func
cat
(
r
reader
)
{
func
cat
(
r
reader
)
{
const
NBUF
=
512
;
const
NBUF
=
512
var
buf
[
NBUF
]
byte
;
var
buf
[
NBUF
]
byte
if
*
rot13Flag
{
if
*
rot13Flag
{
r
=
newRotate13
(
r
)
r
=
newRotate13
(
r
)
...
@@ -59,31 +59,31 @@ func cat(r reader) {
...
@@ -59,31 +59,31 @@ func cat(r reader) {
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
])
if
nw
!=
nr
{
if
nw
!=
nr
{
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: error writing from %s: %s
\n
"
,
r
.
String
(),
ew
.
String
())
;
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: error writing from %s: %s
\n
"
,
r
.
String
(),
ew
.
String
())
}
}
}
}
}
}
}
}
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
)
}
}
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
f
,
err
:=
file
.
Open
(
flag
.
Arg
(
i
),
0
,
0
)
;
f
,
err
:=
file
.
Open
(
flag
.
Arg
(
i
),
0
,
0
)
if
f
==
nil
{
if
f
==
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: can't open %s: error %s
\n
"
,
flag
.
Arg
(
i
),
err
)
;
fmt
.
Fprintf
(
os
.
Stderr
,
"cat: can't open %s: error %s
\n
"
,
flag
.
Arg
(
i
),
err
)
os
.
Exit
(
1
)
;
os
.
Exit
(
1
)
}
}
cat
(
f
)
;
cat
(
f
)
f
.
Close
()
;
f
.
Close
()
}
}
}
}
doc/progs/echo.go
View file @
34356e9a
...
@@ -5,28 +5,28 @@
...
@@ -5,28 +5,28 @@
package
main
package
main
import
(
import
(
"os"
;
"os"
"flag"
;
// command line option parser
"flag"
// command line option parser
)
)
var
omitNewline
=
flag
.
Bool
(
"n"
,
false
,
"don't print final newline"
)
var
omitNewline
=
flag
.
Bool
(
"n"
,
false
,
"don't print final newline"
)
const
(
const
(
Space
=
" "
;
Space
=
" "
Newline
=
"
\n
"
;
Newline
=
"
\n
"
)
)
func
main
()
{
func
main
()
{
flag
.
Parse
()
;
// Scans the arg list and sets up flags
flag
.
Parse
()
// Scans the arg list and sets up flags
var
s
string
=
""
;
var
s
string
=
""
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
for
i
:=
0
;
i
<
flag
.
NArg
();
i
++
{
if
i
>
0
{
if
i
>
0
{
s
+=
Space
s
+=
Space
}
}
s
+=
flag
.
Arg
(
i
)
;
s
+=
flag
.
Arg
(
i
)
}
}
if
!*
omitNewline
{
if
!*
omitNewline
{
s
+=
Newline
s
+=
Newline
}
}
os
.
Stdout
.
WriteString
(
s
)
;
os
.
Stdout
.
WriteString
(
s
)
}
}
doc/progs/file.go
View file @
34356e9a
...
@@ -5,13 +5,13 @@
...
@@ -5,13 +5,13 @@
package
file
package
file
import
(
import
(
"os"
;
"os"
"syscall"
;
"syscall"
)
)
type
File
struct
{
type
File
struct
{
fd
int
;
// file descriptor number
fd
int
// file descriptor number
name
string
;
// file name at Open time
name
string
// file name at Open time
}
}
func
newFile
(
fd
int
,
name
string
)
*
File
{
func
newFile
(
fd
int
,
name
string
)
*
File
{
...
@@ -22,15 +22,15 @@ func newFile(fd int, name string) *File {
...
@@ -22,15 +22,15 @@ func newFile(fd int, name string) *File {
}
}
var
(
var
(
Stdin
=
newFile
(
0
,
"/dev/stdin"
)
;
Stdin
=
newFile
(
0
,
"/dev/stdin"
)
Stdout
=
newFile
(
1
,
"/dev/stdout"
)
;
Stdout
=
newFile
(
1
,
"/dev/stdout"
)
Stderr
=
newFile
(
2
,
"/dev/stderr"
)
;
Stderr
=
newFile
(
2
,
"/dev/stderr"
)
)
)
func
Open
(
name
string
,
mode
int
,
perm
int
)
(
file
*
File
,
err
os
.
Error
)
{
func
Open
(
name
string
,
mode
int
,
perm
int
)
(
file
*
File
,
err
os
.
Error
)
{
r
,
e
:=
syscall
.
Open
(
name
,
mode
,
perm
)
;
r
,
e
:=
syscall
.
Open
(
name
,
mode
,
perm
)
if
e
!=
0
{
if
e
!=
0
{
err
=
os
.
Errno
(
e
)
;
err
=
os
.
Errno
(
e
)
}
}
return
newFile
(
r
,
name
),
err
return
newFile
(
r
,
name
),
err
}
}
...
@@ -39,10 +39,10 @@ func (file *File) Close() os.Error {
...
@@ -39,10 +39,10 @@ func (file *File) Close() os.Error {
if
file
==
nil
{
if
file
==
nil
{
return
os
.
EINVAL
return
os
.
EINVAL
}
}
e
:=
syscall
.
Close
(
file
.
fd
)
;
e
:=
syscall
.
Close
(
file
.
fd
)
file
.
fd
=
-
1
;
// so it can't be closed again
file
.
fd
=
-
1
// so it can't be closed again
if
e
!=
0
{
if
e
!=
0
{
return
os
.
Errno
(
e
)
;
return
os
.
Errno
(
e
)
}
}
return
nil
return
nil
}
}
...
@@ -51,9 +51,9 @@ func (file *File) Read(b []byte) (ret int, err os.Error) {
...
@@ -51,9 +51,9 @@ func (file *File) Read(b []byte) (ret int, err os.Error) {
if
file
==
nil
{
if
file
==
nil
{
return
-
1
,
os
.
EINVAL
return
-
1
,
os
.
EINVAL
}
}
r
,
e
:=
syscall
.
Read
(
file
.
fd
,
b
)
;
r
,
e
:=
syscall
.
Read
(
file
.
fd
,
b
)
if
e
!=
0
{
if
e
!=
0
{
err
=
os
.
Errno
(
e
)
;
err
=
os
.
Errno
(
e
)
}
}
return
int
(
r
),
err
return
int
(
r
),
err
}
}
...
@@ -62,9 +62,9 @@ func (file *File) Write(b []byte) (ret int, err os.Error) {
...
@@ -62,9 +62,9 @@ func (file *File) Write(b []byte) (ret int, err os.Error) {
if
file
==
nil
{
if
file
==
nil
{
return
-
1
,
os
.
EINVAL
return
-
1
,
os
.
EINVAL
}
}
r
,
e
:=
syscall
.
Write
(
file
.
fd
,
b
)
;
r
,
e
:=
syscall
.
Write
(
file
.
fd
,
b
)
if
e
!=
0
{
if
e
!=
0
{
err
=
os
.
Errno
(
e
)
;
err
=
os
.
Errno
(
e
)
}
}
return
int
(
r
),
err
return
int
(
r
),
err
}
}
...
...
doc/progs/helloworld.go
View file @
34356e9a
...
@@ -7,5 +7,5 @@ package main
...
@@ -7,5 +7,5 @@ package main
import
fmt
"fmt"
// Package implementing formatted I/O.
import
fmt
"fmt"
// Package implementing formatted I/O.
func
main
()
{
func
main
()
{
fmt
.
Printf
(
"Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
\n
"
)
;
fmt
.
Printf
(
"Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
\n
"
)
}
}
doc/progs/helloworld3.go
View file @
34356e9a
...
@@ -5,17 +5,17 @@
...
@@ -5,17 +5,17 @@
package
main
package
main
import
(
import
(
"./file"
;
"./file"
"fmt"
;
"fmt"
"os"
;
"os"
)
)
func
main
()
{
func
main
()
{
hello
:=
[]
byte
{
'h'
,
'e'
,
'l'
,
'l'
,
'o'
,
','
,
' '
,
'w'
,
'o'
,
'r'
,
'l'
,
'd'
,
'\n'
}
;
hello
:=
[]
byte
{
'h'
,
'e'
,
'l'
,
'l'
,
'o'
,
','
,
' '
,
'w'
,
'o'
,
'r'
,
'l'
,
'd'
,
'\n'
}
file
.
Stdout
.
Write
(
hello
)
;
file
.
Stdout
.
Write
(
hello
)
file
,
err
:=
file
.
Open
(
"/does/not/exist"
,
0
,
0
)
;
file
,
err
:=
file
.
Open
(
"/does/not/exist"
,
0
,
0
)
if
file
==
nil
{
if
file
==
nil
{
fmt
.
Printf
(
"can't open file; err=%s
\n
"
,
err
.
String
())
;
fmt
.
Printf
(
"can't open file; err=%s
\n
"
,
err
.
String
())
os
.
Exit
(
1
)
;
os
.
Exit
(
1
)
}
}
}
}
doc/progs/print.go
View file @
34356e9a
...
@@ -7,14 +7,17 @@ package main
...
@@ -7,14 +7,17 @@ package main
import
"fmt"
import
"fmt"
func
main
()
{
func
main
()
{
var
u64
uint64
=
1
<<
64
-
1
;
var
u64
uint64
=
1
<<
64
-
1
fmt
.
Printf
(
"%d %d
\n
"
,
u64
,
int64
(
u64
))
;
fmt
.
Printf
(
"%d %d
\n
"
,
u64
,
int64
(
u64
))
// harder stuff
// harder stuff
type
T
struct
{
a
int
;
b
string
};
type
T
struct
{
t
:=
T
{
77
,
"Sunset Strip"
};
a
int
a
:=
[]
int
{
1
,
2
,
3
,
4
};
b
string
fmt
.
Printf
(
"%v %v %v
\n
"
,
u64
,
t
,
a
);
}
fmt
.
Print
(
u64
,
" "
,
t
,
" "
,
a
,
"
\n
"
);
t
:=
T
{
77
,
"Sunset Strip"
}
fmt
.
Println
(
u64
,
t
,
a
);
a
:=
[]
int
{
1
,
2
,
3
,
4
}
fmt
.
Printf
(
"%v %v %v
\n
"
,
u64
,
t
,
a
)
fmt
.
Print
(
u64
,
" "
,
t
,
" "
,
a
,
"
\n
"
)
fmt
.
Println
(
u64
,
t
,
a
)
}
}
doc/progs/print_string.go
View file @
34356e9a
...
@@ -6,13 +6,16 @@ package main
...
@@ -6,13 +6,16 @@ package main
import
"fmt"
import
"fmt"
type
testType
struct
{
a
int
;
b
string
}
type
testType
struct
{
a
int
b
string
}
func
(
t
*
testType
)
String
()
string
{
func
(
t
*
testType
)
String
()
string
{
return
fmt
.
Sprint
(
t
.
a
)
+
" "
+
t
.
b
return
fmt
.
Sprint
(
t
.
a
)
+
" "
+
t
.
b
}
}
func
main
()
{
func
main
()
{
t
:=
&
testType
{
77
,
"Sunset Strip"
}
;
t
:=
&
testType
{
77
,
"Sunset Strip"
}
fmt
.
Println
(
t
)
fmt
.
Println
(
t
)
}
}
doc/progs/server.go
View file @
34356e9a
...
@@ -7,45 +7,45 @@ package main
...
@@ -7,45 +7,45 @@ package main
import
"fmt"
import
"fmt"
type
request
struct
{
type
request
struct
{
a
,
b
int
;
a
,
b
int
replyc
chan
int
;
replyc
chan
int
}
}
type
binOp
func
(
a
,
b
int
)
int
type
binOp
func
(
a
,
b
int
)
int
func
run
(
op
binOp
,
req
*
request
)
{
func
run
(
op
binOp
,
req
*
request
)
{
reply
:=
op
(
req
.
a
,
req
.
b
)
;
reply
:=
op
(
req
.
a
,
req
.
b
)
req
.
replyc
<-
reply
;
req
.
replyc
<-
reply
}
}
func
server
(
op
binOp
,
service
chan
*
request
)
{
func
server
(
op
binOp
,
service
chan
*
request
)
{
for
{
for
{
req
:=
<-
service
;
req
:=
<-
service
go
run
(
op
,
req
)
;
// don't wait for it
go
run
(
op
,
req
)
// don't wait for it
}
}
}
}
func
startServer
(
op
binOp
)
chan
*
request
{
func
startServer
(
op
binOp
)
chan
*
request
{
req
:=
make
(
chan
*
request
)
;
req
:=
make
(
chan
*
request
)
go
server
(
op
,
req
)
;
go
server
(
op
,
req
)
return
req
;
return
req
}
}
func
main
()
{
func
main
()
{
adder
:=
startServer
(
func
(
a
,
b
int
)
int
{
return
a
+
b
})
;
adder
:=
startServer
(
func
(
a
,
b
int
)
int
{
return
a
+
b
})
const
N
=
100
;
const
N
=
100
var
reqs
[
N
]
request
;
var
reqs
[
N
]
request
for
i
:=
0
;
i
<
N
;
i
++
{
for
i
:=
0
;
i
<
N
;
i
++
{
req
:=
&
reqs
[
i
]
;
req
:=
&
reqs
[
i
]
req
.
a
=
i
;
req
.
a
=
i
req
.
b
=
i
+
N
;
req
.
b
=
i
+
N
req
.
replyc
=
make
(
chan
int
)
;
req
.
replyc
=
make
(
chan
int
)
adder
<-
req
;
adder
<-
req
}
}
for
i
:=
N
-
1
;
i
>=
0
;
i
--
{
// doesn't matter what order
for
i
:=
N
-
1
;
i
>=
0
;
i
--
{
// doesn't matter what order
if
<-
reqs
[
i
]
.
replyc
!=
N
+
2
*
i
{
if
<-
reqs
[
i
]
.
replyc
!=
N
+
2
*
i
{
fmt
.
Println
(
"fail at"
,
i
)
;
fmt
.
Println
(
"fail at"
,
i
)
}
}
}
}
fmt
.
Println
(
"done"
)
;
fmt
.
Println
(
"done"
)
}
}
doc/progs/server1.go
View file @
34356e9a
...
@@ -7,50 +7,50 @@ package main
...
@@ -7,50 +7,50 @@ package main
import
"fmt"
import
"fmt"
type
request
struct
{
type
request
struct
{
a
,
b
int
;
a
,
b
int
replyc
chan
int
;
replyc
chan
int
}
}
type
binOp
func
(
a
,
b
int
)
int
type
binOp
func
(
a
,
b
int
)
int
func
run
(
op
binOp
,
req
*
request
)
{
func
run
(
op
binOp
,
req
*
request
)
{
reply
:=
op
(
req
.
a
,
req
.
b
)
;
reply
:=
op
(
req
.
a
,
req
.
b
)
req
.
replyc
<-
reply
;
req
.
replyc
<-
reply
}
}
func
server
(
op
binOp
,
service
chan
*
request
,
quit
chan
bool
)
{
func
server
(
op
binOp
,
service
chan
*
request
,
quit
chan
bool
)
{
for
{
for
{
select
{
select
{
case
req
:=
<-
service
:
case
req
:=
<-
service
:
go
run
(
op
,
req
)
;
// don't wait for it
go
run
(
op
,
req
)
// don't wait for it
case
<-
quit
:
case
<-
quit
:
return
;
return
}
}
}
}
}
}
func
startServer
(
op
binOp
)
(
service
chan
*
request
,
quit
chan
bool
)
{
func
startServer
(
op
binOp
)
(
service
chan
*
request
,
quit
chan
bool
)
{
service
=
make
(
chan
*
request
)
;
service
=
make
(
chan
*
request
)
quit
=
make
(
chan
bool
)
;
quit
=
make
(
chan
bool
)
go
server
(
op
,
service
,
quit
)
;
go
server
(
op
,
service
,
quit
)
return
service
,
quit
;
return
service
,
quit
}
}
func
main
()
{
func
main
()
{
adder
,
quit
:=
startServer
(
func
(
a
,
b
int
)
int
{
return
a
+
b
})
;
adder
,
quit
:=
startServer
(
func
(
a
,
b
int
)
int
{
return
a
+
b
})
const
N
=
100
;
const
N
=
100
var
reqs
[
N
]
request
;
var
reqs
[
N
]
request
for
i
:=
0
;
i
<
N
;
i
++
{
for
i
:=
0
;
i
<
N
;
i
++
{
req
:=
&
reqs
[
i
]
;
req
:=
&
reqs
[
i
]
req
.
a
=
i
;
req
.
a
=
i
req
.
b
=
i
+
N
;
req
.
b
=
i
+
N
req
.
replyc
=
make
(
chan
int
)
;
req
.
replyc
=
make
(
chan
int
)
adder
<-
req
;
adder
<-
req
}
}
for
i
:=
N
-
1
;
i
>=
0
;
i
--
{
// doesn't matter what order
for
i
:=
N
-
1
;
i
>=
0
;
i
--
{
// doesn't matter what order
if
<-
reqs
[
i
]
.
replyc
!=
N
+
2
*
i
{
if
<-
reqs
[
i
]
.
replyc
!=
N
+
2
*
i
{
fmt
.
Println
(
"fail at"
,
i
)
;
fmt
.
Println
(
"fail at"
,
i
)
}
}
}
}
quit
<-
true
;
quit
<-
true
}
}
doc/progs/sieve.go
View file @
34356e9a
...
@@ -17,7 +17,7 @@ func generate(ch chan int) {
...
@@ -17,7 +17,7 @@ func generate(ch chan int) {
// removing those divisible by 'prime'.
// removing those divisible by 'prime'.
func
filter
(
in
,
out
chan
int
,
prime
int
)
{
func
filter
(
in
,
out
chan
int
,
prime
int
)
{
for
{
for
{
i
:=
<-
in
;
// Receive value of new variable 'i' from 'in'.
i
:=
<-
in
// Receive value of new variable 'i' from 'in'.
if
i
%
prime
!=
0
{
if
i
%
prime
!=
0
{
out
<-
i
// Send 'i' to channel 'out'.
out
<-
i
// Send 'i' to channel 'out'.
}
}
...
@@ -26,13 +26,13 @@ func filter(in, out chan int, prime int) {
...
@@ -26,13 +26,13 @@ func filter(in, out chan int, prime int) {
// The prime sieve: Daisy-chain filter processes together.
// The prime sieve: Daisy-chain filter processes together.
func
main
()
{
func
main
()
{
ch
:=
make
(
chan
int
)
;
// Create a new channel.
ch
:=
make
(
chan
int
)
// Create a new channel.
go
generate
(
ch
)
;
// Start generate() as a goroutine.
go
generate
(
ch
)
// Start generate() as a goroutine.
for
{
for
{
prime
:=
<-
ch
;
prime
:=
<-
ch
fmt
.
Println
(
prime
)
;
fmt
.
Println
(
prime
)
ch1
:=
make
(
chan
int
)
;
ch1
:=
make
(
chan
int
)
go
filter
(
ch
,
ch1
,
prime
)
;
go
filter
(
ch
,
ch1
,
prime
)
ch
=
ch1
ch
=
ch1
}
}
}
}
doc/progs/sieve1.go
View file @
34356e9a
...
@@ -8,44 +8,44 @@ import "fmt"
...
@@ -8,44 +8,44 @@ import "fmt"
// Send the sequence 2, 3, 4, ... to returned channel
// Send the sequence 2, 3, 4, ... to returned channel
func
generate
()
chan
int
{
func
generate
()
chan
int
{
ch
:=
make
(
chan
int
)
;
ch
:=
make
(
chan
int
)
go
func
(){
go
func
(){
for
i
:=
2
;
;
i
++
{
for
i
:=
2
;
;
i
++
{
ch
<-
i
ch
<-
i
}
}
}()
;
}()
return
ch
;
return
ch
}
}
// Filter out input values divisible by 'prime', send rest to returned channel
// Filter out input values divisible by 'prime', send rest to returned channel
func
filter
(
in
chan
int
,
prime
int
)
chan
int
{
func
filter
(
in
chan
int
,
prime
int
)
chan
int
{
out
:=
make
(
chan
int
)
;
out
:=
make
(
chan
int
)
go
func
()
{
go
func
()
{
for
{
for
{
if
i
:=
<-
in
;
i
%
prime
!=
0
{
if
i
:=
<-
in
;
i
%
prime
!=
0
{
out
<-
i
out
<-
i
}
}
}
}
}()
;
}()
return
out
;
return
out
}
}
func
sieve
()
chan
int
{
func
sieve
()
chan
int
{
out
:=
make
(
chan
int
)
;
out
:=
make
(
chan
int
)
go
func
()
{
go
func
()
{
ch
:=
generate
()
;
ch
:=
generate
()
for
{
for
{
prime
:=
<-
ch
;
prime
:=
<-
ch
out
<-
prime
;
out
<-
prime
ch
=
filter
(
ch
,
prime
)
;
ch
=
filter
(
ch
,
prime
)
}
}
}()
;
}()
return
out
;
return
out
}
}
func
main
()
{
func
main
()
{
primes
:=
sieve
()
;
primes
:=
sieve
()
for
{
for
{
fmt
.
Println
(
<-
primes
)
;
fmt
.
Println
(
<-
primes
)
}
}
}
}
doc/progs/sort.go
View file @
34356e9a
...
@@ -5,59 +5,59 @@
...
@@ -5,59 +5,59 @@
package
sort
package
sort
type
Interface
interface
{
type
Interface
interface
{
Len
()
int
;
Len
()
int
Less
(
i
,
j
int
)
bool
;
Less
(
i
,
j
int
)
bool
Swap
(
i
,
j
int
)
;
Swap
(
i
,
j
int
)
}
}
func
Sort
(
data
Interface
)
{
func
Sort
(
data
Interface
)
{
for
i
:=
1
;
i
<
data
.
Len
();
i
++
{
for
i
:=
1
;
i
<
data
.
Len
();
i
++
{
for
j
:=
i
;
j
>
0
&&
data
.
Less
(
j
,
j
-
1
);
j
--
{
for
j
:=
i
;
j
>
0
&&
data
.
Less
(
j
,
j
-
1
);
j
--
{
data
.
Swap
(
j
,
j
-
1
)
;
data
.
Swap
(
j
,
j
-
1
)
}
}
}
}
}
}
func
IsSorted
(
data
Interface
)
bool
{
func
IsSorted
(
data
Interface
)
bool
{
n
:=
data
.
Len
()
;
n
:=
data
.
Len
()
for
i
:=
n
-
1
;
i
>
0
;
i
--
{
for
i
:=
n
-
1
;
i
>
0
;
i
--
{
if
data
.
Less
(
i
,
i
-
1
)
{
if
data
.
Less
(
i
,
i
-
1
)
{
return
false
;
return
false
}
}
}
}
return
true
;
return
true
}
}
// Convenience types for common cases
// Convenience types for common cases
type
IntArray
[]
int
type
IntArray
[]
int
func
(
p
IntArray
)
Len
()
int
{
return
len
(
p
)
;
}
func
(
p
IntArray
)
Len
()
int
{
return
len
(
p
)
}
func
(
p
IntArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
;
}
func
(
p
IntArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
}
func
(
p
IntArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
;
}
func
(
p
IntArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
}
type
FloatArray
[]
float
type
FloatArray
[]
float
func
(
p
FloatArray
)
Len
()
int
{
return
len
(
p
)
;
}
func
(
p
FloatArray
)
Len
()
int
{
return
len
(
p
)
}
func
(
p
FloatArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
;
}
func
(
p
FloatArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
}
func
(
p
FloatArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
;
}
func
(
p
FloatArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
}
type
StringArray
[]
string
type
StringArray
[]
string
func
(
p
StringArray
)
Len
()
int
{
return
len
(
p
)
;
}
func
(
p
StringArray
)
Len
()
int
{
return
len
(
p
)
}
func
(
p
StringArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
;
}
func
(
p
StringArray
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
<
p
[
j
]
}
func
(
p
StringArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
;
}
func
(
p
StringArray
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
}
// Convenience wrappers for common cases
// Convenience wrappers for common cases
func
SortInts
(
a
[]
int
)
{
Sort
(
IntArray
(
a
))
;
}
func
SortInts
(
a
[]
int
)
{
Sort
(
IntArray
(
a
))
}
func
SortFloats
(
a
[]
float
)
{
Sort
(
FloatArray
(
a
))
;
}
func
SortFloats
(
a
[]
float
)
{
Sort
(
FloatArray
(
a
))
}
func
SortStrings
(
a
[]
string
)
{
Sort
(
StringArray
(
a
))
;
}
func
SortStrings
(
a
[]
string
)
{
Sort
(
StringArray
(
a
))
}
func
IntsAreSorted
(
a
[]
int
)
bool
{
return
IsSorted
(
IntArray
(
a
))
;
}
func
IntsAreSorted
(
a
[]
int
)
bool
{
return
IsSorted
(
IntArray
(
a
))
}
func
FloatsAreSorted
(
a
[]
float
)
bool
{
return
IsSorted
(
FloatArray
(
a
))
;
}
func
FloatsAreSorted
(
a
[]
float
)
bool
{
return
IsSorted
(
FloatArray
(
a
))
}
func
StringsAreSorted
(
a
[]
string
)
bool
{
return
IsSorted
(
StringArray
(
a
))
;
}
func
StringsAreSorted
(
a
[]
string
)
bool
{
return
IsSorted
(
StringArray
(
a
))
}
doc/progs/sortmain.go
View file @
34356e9a
...
@@ -5,53 +5,53 @@
...
@@ -5,53 +5,53 @@
package
main
package
main
import
(
import
(
"fmt"
;
"fmt"
"sort"
;
"sort"
)
)
func
ints
()
{
func
ints
()
{
data
:=
[]
int
{
74
,
59
,
238
,
-
784
,
9845
,
959
,
905
,
0
,
0
,
42
,
7586
,
-
5467984
,
7586
}
;
data
:=
[]
int
{
74
,
59
,
238
,
-
784
,
9845
,
959
,
905
,
0
,
0
,
42
,
7586
,
-
5467984
,
7586
}
a
:=
sort
.
IntArray
(
data
)
;
a
:=
sort
.
IntArray
(
data
)
sort
.
Sort
(
a
)
;
sort
.
Sort
(
a
)
if
!
sort
.
IsSorted
(
a
)
{
if
!
sort
.
IsSorted
(
a
)
{
panic
()
panic
()
}
}
}
}
func
strings
()
{
func
strings
()
{
data
:=
[]
string
{
"monday"
,
"tuesday"
,
"wednesday"
,
"thursday"
,
"friday"
,
"saturday"
,
"sunday"
}
;
data
:=
[]
string
{
"monday"
,
"tuesday"
,
"wednesday"
,
"thursday"
,
"friday"
,
"saturday"
,
"sunday"
}
a
:=
sort
.
StringArray
(
data
)
;
a
:=
sort
.
StringArray
(
data
)
sort
.
Sort
(
a
)
;
sort
.
Sort
(
a
)
if
!
sort
.
IsSorted
(
a
)
{
if
!
sort
.
IsSorted
(
a
)
{
panic
()
panic
()
}
}
}
}
type
day
struct
{
type
day
struct
{
num
int
;
num
int
shortName
string
;
shortName
string
longName
string
;
longName
string
}
}
type
dayArray
struct
{
type
dayArray
struct
{
data
[]
*
day
;
data
[]
*
day
}
}
func
(
p
*
dayArray
)
Len
()
int
{
return
len
(
p
.
data
)
;
}
func
(
p
*
dayArray
)
Len
()
int
{
return
len
(
p
.
data
)
}
func
(
p
*
dayArray
)
Less
(
i
,
j
int
)
bool
{
return
p
.
data
[
i
]
.
num
<
p
.
data
[
j
]
.
num
;
}
func
(
p
*
dayArray
)
Less
(
i
,
j
int
)
bool
{
return
p
.
data
[
i
]
.
num
<
p
.
data
[
j
]
.
num
}
func
(
p
*
dayArray
)
Swap
(
i
,
j
int
)
{
p
.
data
[
i
],
p
.
data
[
j
]
=
p
.
data
[
j
],
p
.
data
[
i
]
;
}
func
(
p
*
dayArray
)
Swap
(
i
,
j
int
)
{
p
.
data
[
i
],
p
.
data
[
j
]
=
p
.
data
[
j
],
p
.
data
[
i
]
}
func
days
()
{
func
days
()
{
Sunday
:=
day
{
0
,
"SUN"
,
"Sunday"
}
;
Sunday
:=
day
{
0
,
"SUN"
,
"Sunday"
}
Monday
:=
day
{
1
,
"MON"
,
"Monday"
}
;
Monday
:=
day
{
1
,
"MON"
,
"Monday"
}
Tuesday
:=
day
{
2
,
"TUE"
,
"Tuesday"
}
;
Tuesday
:=
day
{
2
,
"TUE"
,
"Tuesday"
}
Wednesday
:=
day
{
3
,
"WED"
,
"Wednesday"
}
;
Wednesday
:=
day
{
3
,
"WED"
,
"Wednesday"
}
Thursday
:=
day
{
4
,
"THU"
,
"Thursday"
}
;
Thursday
:=
day
{
4
,
"THU"
,
"Thursday"
}
Friday
:=
day
{
5
,
"FRI"
,
"Friday"
}
;
Friday
:=
day
{
5
,
"FRI"
,
"Friday"
}
Saturday
:=
day
{
6
,
"SAT"
,
"Saturday"
}
;
Saturday
:=
day
{
6
,
"SAT"
,
"Saturday"
}
data
:=
[]
*
day
{
&
Tuesday
,
&
Thursday
,
&
Wednesday
,
&
Sunday
,
&
Monday
,
&
Friday
,
&
Saturday
}
;
data
:=
[]
*
day
{
&
Tuesday
,
&
Thursday
,
&
Wednesday
,
&
Sunday
,
&
Monday
,
&
Friday
,
&
Saturday
}
a
:=
dayArray
{
data
}
;
a
:=
dayArray
{
data
}
sort
.
Sort
(
&
a
)
;
sort
.
Sort
(
&
a
)
if
!
sort
.
IsSorted
(
&
a
)
{
if
!
sort
.
IsSorted
(
&
a
)
{
panic
()
panic
()
}
}
...
@@ -63,7 +63,7 @@ func days() {
...
@@ -63,7 +63,7 @@ func days() {
func
main
()
{
func
main
()
{
ints
()
;
ints
()
strings
()
;
strings
()
days
()
;
days
()
}
}
doc/progs/strings.go
View file @
34356e9a
...
@@ -8,9 +8,9 @@ import "fmt"
...
@@ -8,9 +8,9 @@ import "fmt"
import
"os"
import
"os"
func
main
()
{
func
main
()
{
s
:=
"hello"
;
s
:=
"hello"
if
s
[
1
]
!=
'e'
{
os
.
Exit
(
1
)
}
if
s
[
1
]
!=
'e'
{
os
.
Exit
(
1
)
}
s
=
"good bye"
;
s
=
"good bye"
var
p
*
string
=
&
s
;
var
p
*
string
=
&
s
*
p
=
"ciao"
;
*
p
=
"ciao"
}
}
doc/progs/sum.go
View file @
34356e9a
...
@@ -7,7 +7,7 @@ package main
...
@@ -7,7 +7,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
...
@@ -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
"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment