Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
898714a9
Commit
898714a9
authored
Nov 08, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tutorial fixes
R=r CC=go-dev
http://go/go-review/1024014
parent
e434f1a7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
106 additions
and
118 deletions
+106
-118
go_tutorial.html
doc/go_tutorial.html
+53
-59
go_tutorial.txt
doc/go_tutorial.txt
+49
-55
cat_rot13.go
doc/progs/cat_rot13.go
+2
-2
echo.go
doc/progs/echo.go
+2
-2
No files found.
doc/go_tutorial.html
View file @
898714a9
...
@@ -38,9 +38,8 @@ our old, now capitalized and package-qualified friend, <code>fmt.Printf</code>.
...
@@ -38,9 +38,8 @@ our old, now capitalized and package-qualified friend, <code>fmt.Printf</code>.
<p>
<p>
Function declarations are introduced with the
<code>
func
</code>
keyword.
Function declarations are introduced with the
<code>
func
</code>
keyword.
<p>
<p>
Notice that string constants can contain Unicode characters, encoded in UTF-8.
String constants can contain Unicode characters, encoded in UTF-8.
Go is defined to accept UTF-8 input. Strings are arrays of bytes, usually used
(In fact, Go source files are defined to be encoded in UTF-8.)
to store Unicode strings represented in UTF-8.
<p>
<p>
The comment convention is the same as in C++:
The comment convention is the same as in C++:
<p>
<p>
...
@@ -92,7 +91,7 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
...
@@ -92,7 +91,7 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
09
"
flag
"
; // command line option parser
09
"
flag
"
; // command line option parser
10 )
10 )
<p>
<p>
12 var
n_flag
= 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 =
"
"
;
...
@@ -108,7 +107,7 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
...
@@ -108,7 +107,7 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
25 }
25 }
26 s += flag.Arg(i)
26 s += flag.Arg(i)
27 }
27 }
28 if !*
n_flag
{
28 if !*
omitNewline
{
29 s += Newline
29 s += Newline
30 }
30 }
31 os.Stdout.WriteString(s);
31 os.Stdout.WriteString(s);
...
@@ -149,7 +148,7 @@ a naming conflict.
...
@@ -149,7 +148,7 @@ a naming conflict.
Given
<code>
os.Stdout
</code>
we can use its
<code>
WriteString
</code>
method to print the string.
Given
<code>
os.Stdout
</code>
we can use its
<code>
WriteString
</code>
method to print the string.
<p>
<p>
Having imported the
<code>
flag
</code>
package, line 12 creates a global variable to hold
Having imported the
<code>
flag
</code>
package, line 12 creates a global variable to hold
the value of echo's
<code>
-n
</code>
flag. The variable
<code>
n_flag
</code>
has type
<code>
*bool
</code>
, pointer
the value of echo's
<code>
-n
</code>
flag. The variable
<code>
omitNewline
</code>
has type
<code>
*bool
</code>
, pointer
to
<code>
bool
</code>
.
to
<code>
bool
</code>
.
<p>
<p>
In
<code>
main.main
</code>
, we parse the arguments (line 20) and then create a local
In
<code>
main.main
</code>
, we parse the arguments (line 20) and then create a local
...
@@ -179,10 +178,6 @@ or we could go even shorter and write the idiom
...
@@ -179,10 +178,6 @@ or we could go even shorter and write the idiom
</pre>
</pre>
<p>
<p>
The
<code>
:=
</code>
operator is used a lot in Go to represent an initializing declaration.
The
<code>
:=
</code>
operator is used a lot in Go to represent an initializing declaration.
(For those who know Limbo, its
<code>
:=
</code>
construct is the same, but notice
that Go has no colon after the name in a full
<code>
var
</code>
declaration.
Also, for simplicity of parsing,
<code>
:=
</code>
only works inside functions, not at
the top level.)
There's one in the
<code>
for
</code>
clause on the next line:
There's one in the
<code>
for
</code>
clause on the next line:
<p>
<p>
<pre>
<!-- progs/echo.go /for/ -->
<pre>
<!-- progs/echo.go /for/ -->
...
@@ -211,7 +206,7 @@ It's defined that way. Falling off the end of <code>main.main</code> means
...
@@ -211,7 +206,7 @@ It's defined that way. Falling off the end of <code>main.main</code> means
</pre>
</pre>
<p>
<p>
The
<code>
os
</code>
package contains other essentials for getting
The
<code>
os
</code>
package contains other essentials for getting
started; for instance,
<code>
os.Args
</code>
is a
n array
used by the
started; for instance,
<code>
os.Args
</code>
is a
slice
used by the
<code>
flag
</code>
package to access the command-line arguments.
<code>
flag
</code>
package to access the command-line arguments.
<p>
<p>
<h2>
An Interlude about Types
</h2>
<h2>
An Interlude about Types
</h2>
...
@@ -225,7 +220,7 @@ they are not the same type. There is also a <code>byte</code> synonym for
...
@@ -225,7 +220,7 @@ they are not the same type. There is also a <code>byte</code> synonym for
<code>
uint8
</code>
, which is the element type for strings.
<code>
uint8
</code>
, which is the element type for strings.
<p>
<p>
Speaking of
<code>
string
</code>
, that's a built-in type as well. Strings are
Speaking of
<code>
string
</code>
, that's a built-in type as well. Strings are
<i>
immutable values
</i>
-
-
they are not just arrays of
<code>
byte
</code>
values.
<i>
immutable values
</i>
- they are not just arrays of
<code>
byte
</code>
values.
Once you've built a string
<i>
value
</i>
, you can't change it, although
Once you've built a string
<i>
value
</i>
, you can't change it, although
of course you can change a string
<i>
variable
</i>
simply by
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:
...
@@ -255,11 +250,11 @@ read on.
...
@@ -255,11 +250,11 @@ read on.
Arrays are declared like this:
Arrays are declared like this:
<p>
<p>
<pre>
<pre>
var array
_of_i
nt [10]int;
var array
OfI
nt [10]int;
</pre>
</pre>
<p>
<p>
Arrays, like strings, are values, but they are mutable. This differs
Arrays, like strings, are values, but they are mutable. This differs
from C, in which
<code>
array
_of_i
nt
</code>
would be usable as a pointer to
<code>
int
</code>
.
from C, in which
<code>
array
OfI
nt
</code>
would be usable as a pointer to
<code>
int
</code>
.
In Go, since arrays are values, it's meaningful (and useful) to talk
In Go, since arrays are values, it's meaningful (and useful) to talk
about pointers to arrays.
about pointers to arrays.
<p>
<p>
...
@@ -275,7 +270,7 @@ an underlying, often anonymous, regular array. Multiple slices
...
@@ -275,7 +270,7 @@ an underlying, often 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>
Slices are
actually
much more common in Go programs than
Slices are much more common in Go programs than
regular arrays; they're more flexible, have reference semantics,
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
...
@@ -284,7 +279,7 @@ array.
...
@@ -284,7 +279,7 @@ array.
<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
automatically
the function, take the address of the array and Go will
create (efficiently) a slice reference and pass that.
create (efficiently) a slice reference and pass that.
<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>
):
...
@@ -307,10 +302,10 @@ and invoke it like this:
...
@@ -307,10 +302,10 @@ and invoke it like this:
<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
after the parameter list.
after the parameter list.
The expression
<code>
[3]int{1,2,3}
</code>
-
-
a type followed by a brace-bounded expression
The expression
<code>
[3]int{1,2,3}
</code>
- a type followed by a brace-bounded expression
-
-
is a constructor for a value, in this case an array of 3
<code>
ints
</code>
. Putting an
<code>
&
</code>
- is a constructor for a value, in this case an array of 3
<code>
ints
</code>
. Putting an
<code>
&
</code>
in front gives us the address of a unique instance of the value. We pass the
in front gives us the address of a unique instance of the value. We pass the
pointer to
<code>
sum()
</code>
by (
automatical
ly) promoting it to a slice.
pointer to
<code>
sum()
</code>
by (
implicit
ly) promoting it to a slice.
<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:
...
@@ -334,15 +329,15 @@ There are also maps, which you can initialize like this:
...
@@ -334,15 +329,15 @@ There are also maps, which you can initialize like this:
<p>
<p>
The built-in function
<code>
len()
</code>
, which returns number of elements,
The built-in function
<code>
len()
</code>
, which returns number of elements,
makes its first appearance in
<code>
sum
</code>
. It works on strings, arrays,
makes its first appearance in
<code>
sum
</code>
. It works on strings, arrays,
slices,
and map
s.
slices,
maps, and channel
s.
<p>
<p>
<p>
<p>
<h2>
An Interlude about Allocation
</h2>
<h2>
An Interlude about Allocation
</h2>
<p>
<p>
Most types in Go are values. If you have an
<code>
int
</code>
or a
<code>
struct
</code>
Most types in Go are values. If you have an
<code>
int
</code>
or a
<code>
struct
</code>
or an array, assignment
or an array, assignment
copies the contents of the object.
To allocate something on the stack,
copies the contents of the object.
just declare a variable. To allocate it on the heap
, use
<code>
new()
</code>
, which
To allocate a new variable
, use
<code>
new()
</code>
, which
returns a pointer to the allocated storage.
returns a pointer to the allocated storage.
<p>
<p>
<pre>
<pre>
...
@@ -373,7 +368,7 @@ If you just declare the map, as in
...
@@ -373,7 +368,7 @@ If you just declare the map, as in
</pre>
</pre>
<p>
<p>
it creates a
<code>
nil
</code>
reference that cannot hold anything. To use the map,
it creates a
<code>
nil
</code>
reference that cannot hold anything. To use the map,
you must first initialize the reference using
<code>
make()
</code>
or by assignment
to
an
you must first initialize the reference using
<code>
make()
</code>
or by assignment
of
an
existing map.
existing map.
<p>
<p>
Note that
<code>
new(T)
</code>
returns type
<code>
*T
</code>
while
<code>
make(T)
</code>
returns type
Note that
<code>
new(T)
</code>
returns type
<code>
*T
</code>
while
<code>
make(T)
</code>
returns type
...
@@ -390,7 +385,7 @@ can overflow only when they are assigned to an integer variable with
...
@@ -390,7 +385,7 @@ can overflow only when they are assigned to an integer variable with
too little precision to represent the value.
too little precision to represent the value.
<p>
<p>
<pre>
<pre>
const hard
_e
ight = (1
<<
100)
>>
97 // legal
const hard
E
ight = (1
<<
100)
>>
97 // legal
</pre>
</pre>
<p>
<p>
There are nuances that deserve redirection to the legalese of the
There are nuances that deserve redirection to the legalese of the
...
@@ -431,10 +426,10 @@ sort of open/close/read/write interface. Here's the start of <code>file.go</cod
...
@@ -431,10 +426,10 @@ sort of open/close/read/write interface. Here's the start of <code>file.go</cod
15 }
15 }
</pre>
</pre>
<p>
<p>
The first
line declares the name of the package --
<code>
file
</code>
-
-
The first
few lines declare the name of the package -
<code>
file
</code>
-
and then
we
import two packages. The
<code>
os
</code>
package hides the differences
and then import two packages. The
<code>
os
</code>
package hides the differences
between various operating systems to give a consistent view of files and
between various operating systems to give a consistent view of files and
so on; here we're
only
going to use its error handling utilities
so on; here we're going to use its error handling utilities
and reproduce the rudiments of its file I/O.
and reproduce the rudiments of its file I/O.
<p>
<p>
The other item is the low-level, external
<code>
syscall
</code>
package, which provides
The other item is the low-level, external
<code>
syscall
</code>
package, which provides
...
@@ -456,7 +451,7 @@ In Go, the term for publicly visible names is ''exported''.
...
@@ -456,7 +451,7 @@ In Go, the term for publicly visible names is ''exported''.
In the case of
<code>
File
</code>
, all its fields are lower case and so invisible to users, but we
In the case of
<code>
File
</code>
, all its fields are lower case and so invisible to users, but we
will soon give it some exported, upper-case methods.
will soon give it some exported, upper-case methods.
<p>
<p>
First, though, here is a factory to create
them
:
First, though, here is a factory to create
a
<code>
File
</code>
:
<p>
<p>
<pre>
<!-- progs/file.go /newFile/ /^}/ -->
<pre>
<!-- progs/file.go /newFile/ /^}/ -->
17 func newFile(fd int, name string) *File {
17 func newFile(fd int, name string) *File {
...
@@ -513,17 +508,16 @@ they look just like a second parameter list. The function
...
@@ -513,17 +508,16 @@ they look just like a second parameter list. The function
<code>
syscall.Open
</code>
<code>
syscall.Open
</code>
also has a multi-value return, which we can grab with the multi-variable
also has a multi-value return, which we can grab with the multi-variable
declaration on line 31; it declares
<code>
r
</code>
and
<code>
e
</code>
to hold the two values,
declaration on line 31; it declares
<code>
r
</code>
and
<code>
e
</code>
to hold the two values,
both of type
<code>
int
64
</code>
(although you'd have to look at the
<code>
syscall
</code>
package
both of type
<code>
int
</code>
(although you'd have to look at the
<code>
syscall
</code>
package
to see that). Finally, line 35 returns two values: a pointer to the new
<code>
File
</code>
to see that). Finally, line 35 returns two values: a pointer to the new
<code>
File
</code>
and the error. If
<code>
syscall.Open
</code>
fails, the file descriptor
<code>
r
</code>
will
and the error. If
<code>
syscall.Open
</code>
fails, the file descriptor
<code>
r
</code>
will
be negative and
<code>
NewFile
</code>
will return
<code>
nil
</code>
.
be negative and
<code>
NewFile
</code>
will return
<code>
nil
</code>
.
<p>
<p>
About those errors: The
<code>
os
</code>
library includes a general notion of an error
About those errors: The
<code>
os
</code>
library includes a general notion of an error.
string, maintaining a unique set of errors throughout the program. It's a
It's a good idea to use its facility in your own interfaces, as we do here, for
good idea to use its facility in your own interfaces, as we do here, for
consistent error handling throughout Go code. In
<code>
Open
</code>
we use a
consistent error handling throughout Go code. In
<code>
Open
</code>
we use a
conversion to
<code>
os.Errno
</code>
to translate Unix's integer
<code>
errno
</code>
value into
conversion to
translate Unix's integer
<code>
errno
</code>
value into the integer type
an error value, which will be stored in a unique instance of type
<code>
os.Error
</code>
.
<code>
os.Errno
</code>
, which implements
<code>
os.Error
</code>
.
<p>
<p>
Now that we can build
<code>
Files
</code>
, we can write methods for them. To declare
Now that we can build
<code>
Files
</code>
, we can write methods for them. To declare
a method of a type, we define a function to have an explicit receiver
a method of a type, we define a function to have an explicit receiver
...
@@ -574,7 +568,7 @@ each of which declares a receiver variable <code>file</code>.
...
@@ -574,7 +568,7 @@ each of which declares a receiver variable <code>file</code>.
There is no implicit
<code>
this
</code>
and the receiver variable must be used to access
There is no implicit
<code>
this
</code>
and the receiver variable must be used to access
members of the structure. Methods are not declared within
members of the structure. Methods are not declared within
the
<code>
struct
</code>
declaration itself. The
<code>
struct
</code>
declaration defines only data members.
the
<code>
struct
</code>
declaration itself. The
<code>
struct
</code>
declaration defines only data members.
In fact, methods can be created for any type you name, such as an integer or
In fact, methods can be created for a
lmost a
ny type you name, such as an integer or
array, not just for
<code>
structs
</code>
. We'll see an example with arrays later.
array, not just for
<code>
structs
</code>
. We'll see an example with arrays later.
<p>
<p>
The
<code>
String
</code>
method is so called because of a printing convention we'll
The
<code>
String
</code>
method is so called because of a printing convention we'll
...
@@ -606,7 +600,7 @@ We can now use our new package:
...
@@ -606,7 +600,7 @@ We can now use our new package:
21 }
21 }
</pre>
</pre>
<p>
<p>
The import of ''
<code>
./file
</code>
'' tells the compiler to use our own package rather than
The
''
<code>
./
</code>
'' in the
import of ''
<code>
./file
</code>
'' tells the compiler to use our own package rather than
something from the directory of installed packages.
something from the directory of installed packages.
<p>
<p>
Finally we can run the program:
Finally we can run the program:
...
@@ -677,7 +671,7 @@ from top to bottom looking for the first case that matches the value; the
...
@@ -677,7 +671,7 @@ from top to bottom looking for the first case that matches the value; the
case expressions don't need to be constants or even integers, as long as
case expressions don't need to be constants or even integers, as long as
they all have the same type.
they all have the same type.
<p>
<p>
Since the
<code>
switch
</code>
value is just
<code>
true
</code>
, we could leave it off -
-
as is also
Since the
<code>
switch
</code>
value is just
<code>
true
</code>
, we could leave it off - as is also
the situation
the situation
in a
<code>
for
</code>
statement, a missing value means
<code>
true
</code>
. In fact, such a
<code>
switch
</code>
in a
<code>
for
</code>
statement, a missing value means
<code>
true
</code>
. In fact, such a
<code>
switch
</code>
is a form of
<code>
if-else
</code>
chain. While we're here, it should be mentioned that in
is a form of
<code>
if-else
</code>
chain. While we're here, it should be mentioned that in
...
@@ -701,8 +695,8 @@ Here is code from <code>progs/cat_rot13.go</code>:
...
@@ -701,8 +695,8 @@ Here is code from <code>progs/cat_rot13.go</code>:
29 }
29 }
</pre>
</pre>
<p>
<p>
Any type that
implements the two methods of
<code>
reader
</code>
-
- regardless of whatever
Any type that
has the two methods of
<code>
reader
</code>
- regardless of whatever
other methods the type may also
contain -
- is said to
<i>
implement
</i>
the
other methods the type may also
have
- is said to
<i>
implement
</i>
the
interface. Since
<code>
file.File
</code>
implements these methods, it implements the
interface. Since
<code>
file.File
</code>
implements these methods, it implements the
<code>
reader
</code>
interface. We could tweak the
<code>
cat
</code>
subroutine to accept a
<code>
reader
</code>
<code>
reader
</code>
interface. We could tweak the
<code>
cat
</code>
subroutine to accept a
<code>
reader
</code>
instead of a
<code>
*file.File
</code>
and it would work just fine, but let's embellish a little
instead of a
<code>
*file.File
</code>
and it would work just fine, but let's embellish a little
...
@@ -738,8 +732,8 @@ we have a second implementation of the <code>reader</code> interface.
...
@@ -738,8 +732,8 @@ we have a second implementation of the <code>reader</code> interface.
<p>
<p>
To use the new feature, we define a flag:
To use the new feature, we define a flag:
<p>
<p>
<pre>
<!-- progs/cat_rot13.go /rot13
_f
lag/ -->
<pre>
<!-- progs/cat_rot13.go /rot13
F
lag/ -->
14 var rot13
_f
lag = flag.Bool(
"
rot13
"
, false,
"
rot13 the input
"
)
14 var rot13
F
lag = flag.Bool(
"
rot13
"
, false,
"
rot13 the input
"
)
</pre>
</pre>
<p>
<p>
and use it from within a mostly unchanged
<code>
cat()
</code>
function:
and use it from within a mostly unchanged
<code>
cat()
</code>
function:
...
@@ -749,7 +743,7 @@ and use it from within a mostly unchanged <code>cat()</code> function:
...
@@ -749,7 +743,7 @@ and use it from within a mostly unchanged <code>cat()</code> function:
53 const NBUF = 512;
53 const NBUF = 512;
54 var buf [NBUF]byte;
54 var buf [NBUF]byte;
<p>
<p>
56 if *rot13
_f
lag {
56 if *rot13
F
lag {
57 r = newRotate13(r)
57 r = newRotate13(r)
58 }
58 }
59 for {
59 for {
...
@@ -789,7 +783,7 @@ Here it is in action:
...
@@ -789,7 +783,7 @@ Here it is in action:
Fans of dependency injection may take cheer from how easily interfaces
Fans of dependency injection may take cheer from how easily interfaces
allow us to substitute the implementation of a file descriptor.
allow us to substitute the implementation of a file descriptor.
<p>
<p>
Interfaces are a distinct feature of Go. An interface is implemented by a
Interfaces are a distinct
ive
feature of Go. An interface is implemented by a
type if the type implements all the methods declared in the interface.
type if the type implements all the methods declared in the interface.
This means
This means
that a type may implement an arbitrary number of different interfaces.
that a type may implement an arbitrary number of different interfaces.
...
@@ -807,7 +801,7 @@ useful for things like containers.
...
@@ -807,7 +801,7 @@ useful for things like containers.
<p>
<p>
<h2>
Sorting
</h2>
<h2>
Sorting
</h2>
<p>
<p>
Interfaces provide a simple form of polymorphism
since t
hey completely
Interfaces provide a simple form of polymorphism
. T
hey completely
separate the definition of what an object does from how it does it, allowing
separate the definition of what an object does from how it does it, allowing
distinct implementations to be represented at different times by the
distinct implementations to be represented at different times by the
same interface variable.
same interface variable.
...
@@ -898,8 +892,8 @@ Within the <code>fmt</code> package, <code>Printf</code> is declared with this s
...
@@ -898,8 +892,8 @@ Within the <code>fmt</code> package, <code>Printf</code> is declared with this s
</pre>
</pre>
<p>
<p>
That
<code>
...
</code>
represents the variadic argument list that in C would
That
<code>
...
</code>
represents the variadic argument list that in C would
be handled using the
<code>
stdarg.h
</code>
macros
,
but in Go is passed using
be handled using the
<code>
stdarg.h
</code>
macros but in Go is passed using
an empty interface variable (
<code>
interface {}
</code>
)
that is
then unpacked
an empty interface variable (
<code>
interface {}
</code>
)
and
then unpacked
using the reflection library. It's off topic here but the use of
using the reflection library. It's off topic here but the use of
reflection helps explain some of the nice properties of Go's
<code>
Printf
</code>
,
reflection helps explain some of the nice properties of Go's
<code>
Printf
</code>
,
due to the ability of
<code>
Printf
</code>
to discover the type of its arguments
due to the ability of
<code>
Printf
</code>
to discover the type of its arguments
...
@@ -940,7 +934,7 @@ is
...
@@ -940,7 +934,7 @@ is
You can drop the formatting altogether if you use
<code>
Print
</code>
or
<code>
Println
</code>
You can drop the formatting altogether if you use
<code>
Print
</code>
or
<code>
Println
</code>
instead of
<code>
Printf
</code>
. Those routines do fully automatic formatting.
instead of
<code>
Printf
</code>
. Those routines do fully automatic formatting.
The
<code>
Print
</code>
function just prints its elements out using the equivalent
The
<code>
Print
</code>
function just prints its elements out using the equivalent
of
<code>
%v
</code>
while
<code>
Println
</code>
automatically
inserts spaces between arguments
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>
...
@@ -968,7 +962,7 @@ Here's a simple example.
...
@@ -968,7 +962,7 @@ Here's a simple example.
18 }
18 }
</pre>
</pre>
<p>
<p>
Since
<code>
*
T
</code>
has a
<code>
String()
</code>
method, the
Since
<code>
*
testType
</code>
has a
<code>
String()
</code>
method, the
default formatter for that type will use it and produce the output
default formatter for that type will use it and produce the output
<p>
<p>
<pre>
<pre>
...
@@ -1039,7 +1033,7 @@ you want.
...
@@ -1039,7 +1033,7 @@ you want.
<p>
<p>
<h2>
Prime numbers
</h2>
<h2>
Prime numbers
</h2>
<p>
<p>
Now we come to processes and communication -
-
concurrent programming.
Now we come to processes and communication - concurrent programming.
It's a big subject so to be brief we assume some familiarity with the topic.
It's a big subject so to be brief we assume some familiarity with the topic.
<p>
<p>
A classic program in the style is a prime sieve.
A classic program in the style is a prime sieve.
...
@@ -1112,7 +1106,7 @@ this starts the function running in parallel with the current
...
@@ -1112,7 +1106,7 @@ this starts the function running in parallel with the current
computation but in the same address space:
computation but in the same address space:
<p>
<p>
<pre>
<pre>
go sum(huge
_a
rray); // calculate sum in the background
go sum(huge
A
rray); // calculate sum in the background
</pre>
</pre>
<p>
<p>
If you want to know when the calculation is done, pass a channel
If you want to know when the calculation is done, pass a channel
...
@@ -1120,7 +1114,7 @@ on which it can report back:
...
@@ -1120,7 +1114,7 @@ on which it can report back:
<p>
<p>
<pre>
<pre>
ch := make(chan int);
ch := make(chan int);
go sum(huge
_a
rray, ch);
go sum(huge
A
rray, ch);
// ... do something else for a while
// ... do something else for a while
result :=
<
-ch; // wait for, and retrieve, result
result :=
<
-ch; // wait for, and retrieve, result
</pre>
</pre>
...
@@ -1164,7 +1158,7 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
...
@@ -1164,7 +1158,7 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
</pre>
</pre>
<p>
<p>
This version does all the setup internally. It creates the output
This version does all the setup internally. It creates the output
channel, launches a goroutine
internally us
ing a function literal, and
channel, launches a goroutine
runn
ing a function literal, and
returns the channel to the caller. It is a factory for concurrent
returns the channel to the caller. It is a factory for concurrent
execution, starting the goroutine and returning its connection.
execution, starting the goroutine and returning its connection.
<p>
<p>
...
@@ -1221,7 +1215,7 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
...
@@ -1221,7 +1215,7 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
<h2>
Multiplexing
</h2>
<h2>
Multiplexing
</h2>
<p>
<p>
With channels, it's possible to serve multiple independent client goroutines without
With channels, it's possible to serve multiple independent client goroutines without
writing an
actual
multiplexer. The trick is to send the server a channel in the message,
writing an
explicit
multiplexer. The trick is to send the server a channel in the message,
which it will then use to reply to the original sender.
which it will then use to reply to the original sender.
A realistic client-server program is a lot of code, so here is a very simple substitute
A realistic client-server program is a lot of code, so here is a very simple substitute
to illustrate the idea. It starts by defining a
<code>
request
</code>
type, which embeds a channel
to illustrate the idea. It starts by defining a
<code>
request
</code>
type, which embeds a channel
...
@@ -1261,8 +1255,8 @@ a long-running operation, starting a goroutine to do the actual work.
...
@@ -1261,8 +1255,8 @@ a long-running operation, starting a goroutine to do the actual work.
26 }
26 }
</pre>
</pre>
<p>
<p>
We construct a server in a familiar way, starting it
up and returning a channel to
We construct a server in a familiar way, starting it
and returning a channel
connect to it:
connect
ed
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 {
...
@@ -1272,8 +1266,8 @@ connect to it:
...
@@ -1272,8 +1266,8 @@ connect to it:
32 }
32 }
</pre>
</pre>
<p>
<p>
Here's a simple test. It starts a server with an addition operator
,
and sends out
Here's a simple test. It starts a server with an addition operator and sends out
lots of requests but doesn't wait for the reply
. Only after all the requests are sent
<code>
N
</code>
requests without waiting for the replies
. Only after all the requests are sent
does it check the results.
does it check the results.
<p>
<p>
<pre>
<!-- progs/server.go /func.main/ /^}/ -->
<pre>
<!-- progs/server.go /func.main/ /^}/ -->
...
@@ -1297,7 +1291,7 @@ does it check the results.
...
@@ -1297,7 +1291,7 @@ does it check the results.
51 }
51 }
</pre>
</pre>
<p>
<p>
One annoyance with this program is that it doesn't
exit
cleanly; when
<code>
main
</code>
returns
One annoyance with this program is that it doesn't
shut down the server
cleanly; when
<code>
main
</code>
returns
there are a number of lingering goroutines blocked on communication. To solve this,
there are a number of lingering goroutines blocked on communication. To solve this,
we can provide a second,
<code>
quit
</code>
channel to the server:
we can provide a second,
<code>
quit
</code>
channel to the server:
<p>
<p>
...
@@ -1325,7 +1319,7 @@ It passes the quit channel to the <code>server</code> function, which uses it li
...
@@ -1325,7 +1319,7 @@ It passes the quit channel to the <code>server</code> function, which uses it li
30 }
30 }
</pre>
</pre>
<p>
<p>
Inside
<code>
server
</code>
,
a
<code>
select
</code>
statement chooses which of the multiple communications
Inside
<code>
server
</code>
,
the
<code>
select
</code>
statement chooses which of the multiple communications
listed by its cases can proceed. If all are blocked, it waits until one can proceed; if
listed by its cases can proceed. If all are blocked, it waits until one can proceed; if
multiple can proceed, it chooses one at random. In this instance, the
<code>
select
</code>
allows
multiple can proceed, it chooses one at random. In this instance, the
<code>
select
</code>
allows
the server to honor requests until it receives a quit message, at which point it
the server to honor requests until it receives a quit message, at which point it
...
...
doc/go_tutorial.txt
View file @
898714a9
...
@@ -32,9 +32,8 @@ our old, now capitalized and package-qualified friend, "fmt.Printf".
...
@@ -32,9 +32,8 @@ our old, now capitalized and package-qualified friend, "fmt.Printf".
Function declarations are introduced with the "func" keyword.
Function declarations are introduced with the "func" keyword.
Notice that string constants can contain Unicode characters, encoded in UTF-8.
String constants can contain Unicode characters, encoded in UTF-8.
Go is defined to accept UTF-8 input. Strings are arrays of bytes, usually used
(In fact, Go source files are defined to be encoded in UTF-8.)
to store Unicode strings represented in UTF-8.
The comment convention is the same as in C++:
The comment convention is the same as in C++:
...
@@ -108,7 +107,7 @@ a naming conflict.
...
@@ -108,7 +107,7 @@ a naming conflict.
Given "os.Stdout" we can use its "WriteString" method to print the string.
Given "os.Stdout" we can use its "WriteString" method to print the string.
Having imported the "flag" package, line 12 creates a global variable to hold
Having imported the "flag" package, line 12 creates a global variable to hold
the value of echo's "-n" flag. The variable "
n_flag
" has type "*bool", pointer
the value of echo's "-n" flag. The variable "
omitNewline
" has type "*bool", pointer
to "bool".
to "bool".
In "main.main", we parse the arguments (line 20) and then create a local
In "main.main", we parse the arguments (line 20) and then create a local
...
@@ -132,10 +131,6 @@ or we could go even shorter and write the idiom
...
@@ -132,10 +131,6 @@ or we could go even shorter and write the idiom
s := "";
s := "";
The ":=" operator is used a lot in Go to represent an initializing declaration.
The ":=" operator is used a lot in Go to represent an initializing declaration.
(For those who know Limbo, its ":=" construct is the same, but notice
that Go has no colon after the name in a full "var" declaration.
Also, for simplicity of parsing, ":=" only works inside functions, not at
the top level.)
There's one in the "for" clause on the next line:
There's one in the "for" clause on the next line:
--PROG progs/echo.go /for/
--PROG progs/echo.go /for/
...
@@ -160,7 +155,7 @@ It's defined that way. Falling off the end of "main.main" means
...
@@ -160,7 +155,7 @@ It's defined that way. Falling off the end of "main.main" means
os.Exit(1)
os.Exit(1)
The "os" package contains other essentials for getting
The "os" package contains other essentials for getting
started; for instance, "os.Args" is a
n array
used by the
started; for instance, "os.Args" is a
slice
used by the
"flag" package to access the command-line arguments.
"flag" package to access the command-line arguments.
An Interlude about Types
An Interlude about Types
...
@@ -175,7 +170,7 @@ they are not the same type. There is also a "byte" synonym for
...
@@ -175,7 +170,7 @@ they are not the same type. There is also a "byte" synonym for
"uint8", which is the element type for strings.
"uint8", which is the element type for strings.
Speaking of "string", that's a built-in type as well. Strings are
Speaking of "string", that's a built-in type as well. Strings are
<i>immutable values</i> -
-
they are not just arrays of "byte" values.
<i>immutable values</i> - they are not just arrays of "byte" values.
Once you've built a string <i>value</i>, you can't change it, although
Once you've built a string <i>value</i>, you can't change it, although
of course you can change a string <i>variable</i> simply by
of course you can change a string <i>variable</i> simply by
reassigning it. This snippet from "strings.go" is legal code:
reassigning it. This snippet from "strings.go" is legal code:
...
@@ -196,10 +191,10 @@ read on.
...
@@ -196,10 +191,10 @@ read on.
Arrays are declared like this:
Arrays are declared like this:
var array
_of_i
nt [10]int;
var array
OfI
nt [10]int;
Arrays, like strings, are values, but they are mutable. This differs
Arrays, like strings, are values, but they are mutable. This differs
from C, in which "array
_of_i
nt" would be usable as a pointer to "int".
from C, in which "array
OfI
nt" would be usable as a pointer to "int".
In Go, since arrays are values, it's meaningful (and useful) to talk
In Go, since arrays are values, it's meaningful (and useful) to talk
about pointers to arrays.
about pointers to arrays.
...
@@ -215,7 +210,7 @@ an underlying, often anonymous, regular array. Multiple slices
...
@@ -215,7 +210,7 @@ an underlying, often 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.
Slices are
actually
much more common in Go programs than
Slices are much more common in Go programs than
regular arrays; they're more flexible, have reference semantics,
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
...
@@ -224,7 +219,7 @@ array.
...
@@ -224,7 +219,7 @@ array.
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
automatically
the function, take the address of the array and Go will
create (efficiently) a slice reference and pass that.
create (efficiently) a slice reference and pass that.
Using slices one can write this function (from "sum.go"):
Using slices one can write this function (from "sum.go"):
...
@@ -237,10 +232,10 @@ and invoke it like this:
...
@@ -237,10 +232,10 @@ and invoke it like this:
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 expression
The expression "[3]int{1,2,3}" - a type followed by a brace-bounded expression
-
-
is a constructor for a value, in this case an array of 3 "ints". Putting an "&"
- is a constructor for a value, in this case an array of 3 "ints". Putting an "&"
in front gives us the address of a unique instance of the value. We pass the
in front gives us the address of a unique instance of the value. We pass the
pointer to "sum()" by (
automatical
ly) promoting it to a slice.
pointer to "sum()" by (
implicit
ly) 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:
...
@@ -258,7 +253,7 @@ There are also maps, which you can initialize like this:
...
@@ -258,7 +253,7 @@ There are also maps, which you can initialize like this:
The built-in function "len()", which returns number of elements,
The built-in function "len()", which returns number of elements,
makes its first appearance in "sum". It works on strings, arrays,
makes its first appearance in "sum". It works on strings, arrays,
slices,
and map
s.
slices,
maps, and channel
s.
An Interlude about Allocation
An Interlude about Allocation
...
@@ -266,8 +261,8 @@ An Interlude about Allocation
...
@@ -266,8 +261,8 @@ An Interlude about Allocation
Most types in Go are values. If you have an "int" or a "struct"
Most types in Go are values. If you have an "int" or a "struct"
or an array, assignment
or an array, assignment
copies the contents of the object.
To allocate something on the stack,
copies the contents of the object.
just declare a variable. To allocate it on the heap
, use "new()", which
To allocate a new variable
, use "new()", which
returns a pointer to the allocated storage.
returns a pointer to the allocated storage.
type T struct { a, b int }
type T struct { a, b int }
...
@@ -290,7 +285,7 @@ If you just declare the map, as in
...
@@ -290,7 +285,7 @@ If you just declare the map, as in
var m map[string]int;
var m map[string]int;
it creates a "nil" reference that cannot hold anything. To use the map,
it creates a "nil" reference that cannot hold anything. To use the map,
you must first initialize the reference using "make()" or by assignment
to
an
you must first initialize the reference using "make()" or by assignment
of
an
existing map.
existing map.
Note that "new(T)" returns type "*T" while "make(T)" returns type
Note that "new(T)" returns type "*T" while "make(T)" returns type
...
@@ -307,7 +302,7 @@ constants are evaluated as large-precision values that
...
@@ -307,7 +302,7 @@ constants are evaluated as large-precision values that
can overflow only when they are assigned to an integer variable with
can overflow only when they are assigned to an integer variable with
too little precision to represent the value.
too little precision to represent the value.
const hard
_e
ight = (1 << 100) >> 97 // legal
const hard
E
ight = (1 << 100) >> 97 // legal
There are nuances that deserve redirection to the legalese of the
There are nuances that deserve redirection to the legalese of the
language specification but here are some illustrative examples:
language specification but here are some illustrative examples:
...
@@ -334,10 +329,10 @@ sort of open/close/read/write interface. Here's the start of "file.go":
...
@@ -334,10 +329,10 @@ sort of open/close/read/write interface. Here's the start of "file.go":
--PROG progs/file.go /package/ /^}/
--PROG progs/file.go /package/ /^}/
The first
line declares the name of the package -- "file" -
-
The first
few lines declare the name of the package - "file"
-
and then
we
import two packages. The "os" package hides the differences
and then import two packages. The "os" package hides the differences
between various operating systems to give a consistent view of files and
between various operating systems to give a consistent view of files and
so on; here we're
only
going to use its error handling utilities
so on; here we're going to use its error handling utilities
and reproduce the rudiments of its file I/O.
and reproduce the rudiments of its file I/O.
The other item is the low-level, external "syscall" package, which provides
The other item is the low-level, external "syscall" package, which provides
...
@@ -359,7 +354,7 @@ In Go, the term for publicly visible names is ''exported''.
...
@@ -359,7 +354,7 @@ In Go, the term for publicly visible names is ''exported''.
In the case of "File", all its fields are lower case and so invisible to users, but we
In the case of "File", all its fields are lower case and so invisible to users, but we
will soon give it some exported, upper-case methods.
will soon give it some exported, upper-case methods.
First, though, here is a factory to create
them
:
First, though, here is a factory to create
a "File"
:
--PROG progs/file.go /newFile/ /^}/
--PROG progs/file.go /newFile/ /^}/
...
@@ -393,17 +388,16 @@ they look just like a second parameter list. The function
...
@@ -393,17 +388,16 @@ they look just like a second parameter list. The function
"syscall.Open"
"syscall.Open"
also has a multi-value return, which we can grab with the multi-variable
also has a multi-value return, which we can grab with the multi-variable
declaration on line 31; it declares "r" and "e" to hold the two values,
declaration on line 31; it declares "r" and "e" to hold the two values,
both of type "int
64
" (although you'd have to look at the "syscall" package
both of type "int" (although you'd have to look at the "syscall" package
to see that). Finally, line 35 returns two values: a pointer to the new "File"
to see that). Finally, line 35 returns two values: a pointer to the new "File"
and the error. If "syscall.Open" fails, the file descriptor "r" will
and the error. If "syscall.Open" fails, the file descriptor "r" will
be negative and "NewFile" will return "nil".
be negative and "NewFile" will return "nil".
About those errors: The "os" library includes a general notion of an error
About those errors: The "os" library includes a general notion of an error.
string, maintaining a unique set of errors throughout the program. It's a
It's a good idea to use its facility in your own interfaces, as we do here, for
good idea to use its facility in your own interfaces, as we do here, for
consistent error handling throughout Go code. In "Open" we use a
consistent error handling throughout Go code. In "Open" we use a
conversion to
"os.Errno" to translate Unix's integer "errno" value into
conversion to
translate Unix's integer "errno" value into the integer type
an error value, which will be stored in a unique instance of type
"os.Error".
"os.Errno", which implements
"os.Error".
Now that we can build "Files", we can write methods for them. To declare
Now that we can build "Files", we can write methods for them. To declare
a method of a type, we define a function to have an explicit receiver
a method of a type, we define a function to have an explicit receiver
...
@@ -416,7 +410,7 @@ each of which declares a receiver variable "file".
...
@@ -416,7 +410,7 @@ each of which declares a receiver variable "file".
There is no implicit "this" and the receiver variable must be used to access
There is no implicit "this" and the receiver variable must be used to access
members of the structure. Methods are not declared within
members of the structure. Methods are not declared within
the "struct" declaration itself. The "struct" declaration defines only data members.
the "struct" declaration itself. The "struct" declaration defines only data members.
In fact, methods can be created for any type you name, such as an integer or
In fact, methods can be created for a
lmost a
ny type you name, such as an integer or
array, not just for "structs". We'll see an example with arrays later.
array, not just for "structs". We'll see an example with arrays later.
The "String" method is so called because of a printing convention we'll
The "String" method is so called because of a printing convention we'll
...
@@ -430,7 +424,7 @@ We can now use our new package:
...
@@ -430,7 +424,7 @@ We can now use our new package:
--PROG progs/helloworld3.go /package/ END
--PROG progs/helloworld3.go /package/ END
The import of ''"./file"'' tells the compiler to use our own package rather than
The
''"./"'' in the
import of ''"./file"'' tells the compiler to use our own package rather than
something from the directory of installed packages.
something from the directory of installed packages.
Finally we can run the program:
Finally we can run the program:
...
@@ -457,7 +451,7 @@ from top to bottom looking for the first case that matches the value; the
...
@@ -457,7 +451,7 @@ from top to bottom looking for the first case that matches the value; the
case expressions don't need to be constants or even integers, as long as
case expressions don't need to be constants or even integers, as long as
they all have the same type.
they all have the same type.
Since the "switch" value is just "true", we could leave it off -
-
as is also
Since the "switch" value is just "true", we could leave it off - as is also
the situation
the situation
in a "for" statement, a missing value means "true". In fact, such a "switch"
in a "for" statement, a missing value means "true". In fact, such a "switch"
is a form of "if-else" chain. While we're here, it should be mentioned that in
is a form of "if-else" chain. While we're here, it should be mentioned that in
...
@@ -476,8 +470,8 @@ Here is code from "progs/cat_rot13.go":
...
@@ -476,8 +470,8 @@ Here is code from "progs/cat_rot13.go":
--PROG progs/cat_rot13.go /type.reader/ /^}/
--PROG progs/cat_rot13.go /type.reader/ /^}/
Any type that
implements the two methods of "reader" -
- regardless of whatever
Any type that
has the two methods of "reader"
- regardless of whatever
other methods the type may also
contain -
- is said to <i>implement</i> the
other methods the type may also
have
- is said to <i>implement</i> the
interface. Since "file.File" implements these methods, it implements the
interface. Since "file.File" implements these methods, it implements the
"reader" interface. We could tweak the "cat" subroutine to accept a "reader"
"reader" interface. We could tweak the "cat" subroutine to accept a "reader"
instead of a "*file.File" and it would work just fine, but let's embellish a little
instead of a "*file.File" and it would work just fine, but let's embellish a little
...
@@ -492,7 +486,7 @@ we have a second implementation of the "reader" interface.
...
@@ -492,7 +486,7 @@ we have a second implementation of the "reader" interface.
To use the new feature, we define a flag:
To use the new feature, we define a flag:
--PROG progs/cat_rot13.go /rot13
_f
lag/
--PROG progs/cat_rot13.go /rot13
F
lag/
and use it from within a mostly unchanged "cat()" function:
and use it from within a mostly unchanged "cat()" function:
...
@@ -518,7 +512,7 @@ Here it is in action:
...
@@ -518,7 +512,7 @@ Here it is in action:
Fans of dependency injection may take cheer from how easily interfaces
Fans of dependency injection may take cheer from how easily interfaces
allow us to substitute the implementation of a file descriptor.
allow us to substitute the implementation of a file descriptor.
Interfaces are a distinct feature of Go. An interface is implemented by a
Interfaces are a distinct
ive
feature of Go. An interface is implemented by a
type if the type implements all the methods declared in the interface.
type if the type implements all the methods declared in the interface.
This means
This means
that a type may implement an arbitrary number of different interfaces.
that a type may implement an arbitrary number of different interfaces.
...
@@ -537,7 +531,7 @@ useful for things like containers.
...
@@ -537,7 +531,7 @@ useful for things like containers.
Sorting
Sorting
----
----
Interfaces provide a simple form of polymorphism
since t
hey completely
Interfaces provide a simple form of polymorphism
. T
hey completely
separate the definition of what an object does from how it does it, allowing
separate the definition of what an object does from how it does it, allowing
distinct implementations to be represented at different times by the
distinct implementations to be represented at different times by the
same interface variable.
same interface variable.
...
@@ -584,8 +578,8 @@ Within the "fmt" package, "Printf" is declared with this signature:
...
@@ -584,8 +578,8 @@ Within the "fmt" package, "Printf" is declared with this signature:
Printf(format string, v ...) (n int, errno os.Error)
Printf(format string, v ...) (n int, errno os.Error)
That "..." represents the variadic argument list that in C would
That "..." represents the variadic argument list that in C would
be handled using the "stdarg.h" macros
,
but in Go is passed using
be handled using the "stdarg.h" macros but in Go is passed using
an empty interface variable ("interface {}")
that is
then unpacked
an empty interface variable ("interface {}")
and
then unpacked
using the reflection library. It's off topic here but the use of
using the reflection library. It's off topic here but the use of
reflection helps explain some of the nice properties of Go's "Printf",
reflection helps explain some of the nice properties of Go's "Printf",
due to the ability of "Printf" to discover the type of its arguments
due to the ability of "Printf" to discover the type of its arguments
...
@@ -614,7 +608,7 @@ is
...
@@ -614,7 +608,7 @@ is
You can drop the formatting altogether if you use "Print" or "Println"
You can drop the formatting altogether if you use "Print" or "Println"
instead of "Printf". Those routines do fully automatic formatting.
instead of "Printf". Those routines do fully automatic formatting.
The "Print" function just prints its elements out using the equivalent
The "Print" function just prints its elements out using the equivalent
of "%v" while "Println"
automatically
inserts spaces between arguments
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.
...
@@ -628,7 +622,7 @@ Here's a simple example.
...
@@ -628,7 +622,7 @@ Here's a simple example.
--PROG progs/print_string.go 'NR==9' END
--PROG progs/print_string.go 'NR==9' END
Since "*
T
" has a "String()" method, the
Since "*
testType
" has a "String()" method, the
default formatter for that type will use it and produce the output
default formatter for that type will use it and produce the output
77 Sunset Strip
77 Sunset Strip
...
@@ -692,7 +686,7 @@ you want.
...
@@ -692,7 +686,7 @@ you want.
Prime numbers
Prime numbers
----
----
Now we come to processes and communication -
-
concurrent programming.
Now we come to processes and communication - concurrent programming.
It's a big subject so to be brief we assume some familiarity with the topic.
It's a big subject so to be brief we assume some familiarity with the topic.
A classic program in the style is a prime sieve.
A classic program in the style is a prime sieve.
...
@@ -746,13 +740,13 @@ invoke the function, prefixing the call with the keyword "go";
...
@@ -746,13 +740,13 @@ invoke the function, prefixing the call with the keyword "go";
this starts the function running in parallel with the current
this starts the function running in parallel with the current
computation but in the same address space:
computation but in the same address space:
go sum(huge
_a
rray); // calculate sum in the background
go sum(huge
A
rray); // calculate sum in the background
If you want to know when the calculation is done, pass a channel
If you want to know when the calculation is done, pass a channel
on which it can report back:
on which it can report back:
ch := make(chan int);
ch := make(chan int);
go sum(huge
_a
rray, ch);
go sum(huge
A
rray, ch);
// ... do something else for a while
// ... do something else for a while
result := <-ch; // wait for, and retrieve, result
result := <-ch; // wait for, and retrieve, result
...
@@ -773,7 +767,7 @@ of "generate", from "progs/sieve1.go":
...
@@ -773,7 +767,7 @@ of "generate", from "progs/sieve1.go":
--PROG progs/sieve1.go /func.generate/ /^}/
--PROG progs/sieve1.go /func.generate/ /^}/
This version does all the setup internally. It creates the output
This version does all the setup internally. It creates the output
channel, launches a goroutine
internally us
ing a function literal, and
channel, launches a goroutine
runn
ing a function literal, and
returns the channel to the caller. It is a factory for concurrent
returns the channel to the caller. It is a factory for concurrent
execution, starting the goroutine and returning its connection.
execution, starting the goroutine and returning its connection.
...
@@ -799,7 +793,7 @@ Multiplexing
...
@@ -799,7 +793,7 @@ Multiplexing
----
----
With channels, it's possible to serve multiple independent client goroutines without
With channels, it's possible to serve multiple independent client goroutines without
writing an
actual
multiplexer. The trick is to send the server a channel in the message,
writing an
explicit
multiplexer. The trick is to send the server a channel in the message,
which it will then use to reply to the original sender.
which it will then use to reply to the original sender.
A realistic client-server program is a lot of code, so here is a very simple substitute
A realistic client-server program is a lot of code, so here is a very simple substitute
to illustrate the idea. It starts by defining a "request" type, which embeds a channel
to illustrate the idea. It starts by defining a "request" type, which embeds a channel
...
@@ -820,18 +814,18 @@ a long-running operation, starting a goroutine to do the actual work.
...
@@ -820,18 +814,18 @@ a long-running operation, starting a goroutine to do the actual work.
--PROG progs/server.go /func.server/ /^}/
--PROG progs/server.go /func.server/ /^}/
We construct a server in a familiar way, starting it
up and returning a channel to
We construct a server in a familiar way, starting it
and returning a channel
connect to it:
connect
ed
to it:
--PROG progs/server.go /func.startServer/ /^}/
--PROG progs/server.go /func.startServer/ /^}/
Here's a simple test. It starts a server with an addition operator
,
and sends out
Here's a simple test. It starts a server with an addition operator and sends out
lots of requests but doesn't wait for the reply
. Only after all the requests are sent
"N" requests without waiting for the replies
. Only after all the requests are sent
does it check the results.
does it check the results.
--PROG progs/server.go /func.main/ /^}/
--PROG progs/server.go /func.main/ /^}/
One annoyance with this program is that it doesn't
exit
cleanly; when "main" returns
One annoyance with this program is that it doesn't
shut down the server
cleanly; when "main" returns
there are a number of lingering goroutines blocked on communication. To solve this,
there are a number of lingering goroutines blocked on communication. To solve this,
we can provide a second, "quit" channel to the server:
we can provide a second, "quit" channel to the server:
...
@@ -841,7 +835,7 @@ It passes the quit channel to the "server" function, which uses it like this:
...
@@ -841,7 +835,7 @@ It passes the quit channel to the "server" function, which uses it like this:
--PROG progs/server1.go /func.server/ /^}/
--PROG progs/server1.go /func.server/ /^}/
Inside "server",
a
"select" statement chooses which of the multiple communications
Inside "server",
the
"select" statement chooses which of the multiple communications
listed by its cases can proceed. If all are blocked, it waits until one can proceed; if
listed by its cases can proceed. If all are blocked, it waits until one can proceed; if
multiple can proceed, it chooses one at random. In this instance, the "select" allows
multiple can proceed, it chooses one at random. In this instance, the "select" allows
the server to honor requests until it receives a quit message, at which point it
the server to honor requests until it receives a quit message, at which point it
...
...
doc/progs/cat_rot13.go
View file @
898714a9
...
@@ -11,7 +11,7 @@ import (
...
@@ -11,7 +11,7 @@ import (
"os"
;
"os"
;
)
)
var
rot13
_f
lag
=
flag
.
Bool
(
"rot13"
,
false
,
"rot13 the input"
)
var
rot13
F
lag
=
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'
{
...
@@ -53,7 +53,7 @@ func cat(r reader) {
...
@@ -53,7 +53,7 @@ func cat(r reader) {
const
NBUF
=
512
;
const
NBUF
=
512
;
var
buf
[
NBUF
]
byte
;
var
buf
[
NBUF
]
byte
;
if
*
rot13
_f
lag
{
if
*
rot13
F
lag
{
r
=
newRotate13
(
r
)
r
=
newRotate13
(
r
)
}
}
for
{
for
{
...
...
doc/progs/echo.go
View file @
898714a9
...
@@ -9,7 +9,7 @@ import (
...
@@ -9,7 +9,7 @@ import (
"flag"
;
// command line option parser
"flag"
;
// command line option parser
)
)
var
n_flag
=
flag
.
Bool
(
"n"
,
false
,
"don't print final newline"
)
var
omitNewline
=
flag
.
Bool
(
"n"
,
false
,
"don't print final newline"
)
const
(
const
(
Space
=
" "
;
Space
=
" "
;
...
@@ -25,7 +25,7 @@ func main() {
...
@@ -25,7 +25,7 @@ func main() {
}
}
s
+=
flag
.
Arg
(
i
)
s
+=
flag
.
Arg
(
i
)
}
}
if
!*
n_flag
{
if
!*
omitNewline
{
s
+=
Newline
s
+=
Newline
}
}
os
.
Stdout
.
WriteString
(
s
);
os
.
Stdout
.
WriteString
(
s
);
...
...
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