mirror of
https://github.com/golang/go
synced 2024-11-21 21:14:47 -07:00
Minor cleanups.
These are all fairly trivial and may be ignored. R=r CC=go-dev http://go/go-review/1024025
This commit is contained in:
parent
ceb6031ecd
commit
97a55a7485
@ -31,12 +31,13 @@ Let's start in the usual way:
|
||||
</pre>
|
||||
<p>
|
||||
Every Go source file declares, using a <code>package</code> statement, which package it's part of.
|
||||
The <code>main</code> package's <code>main</code> function is where the program starts running (after
|
||||
any initialization). It may also import other packages to use their facilities.
|
||||
It may also import other packages to use their facilities.
|
||||
This program imports the package <code>fmt</code> to gain access to
|
||||
our old, now capitalized and package-qualified friend, <code>fmt.Printf</code>.
|
||||
our old, now capitalized and package-qualified, friend, <code>fmt.Printf</code>.
|
||||
<p>
|
||||
Function declarations are introduced with the <code>func</code> keyword.
|
||||
Functions are introduced with the <code>func</code> keyword.
|
||||
The <code>main</code> package's <code>main</code> function is where the program starts running (after
|
||||
any initialization).
|
||||
<p>
|
||||
String constants can contain Unicode characters, encoded in UTF-8.
|
||||
(In fact, Go source files are defined to be encoded in UTF-8.)
|
||||
@ -127,7 +128,7 @@ But it's not necessary to do so; we could have said
|
||||
</pre>
|
||||
<p>
|
||||
Semicolons aren't needed here; in fact, semicolons are unnecessary after any
|
||||
top-level declaration, even though they are needed as separators <i>within</i>
|
||||
top-level declaration, although they are needed as separators <i>within</i>
|
||||
a parenthesized list of declarations.
|
||||
<p>
|
||||
This program imports the <code>"os"</code> package to access its <code>Stdout</code> variable, of type
|
||||
@ -213,14 +214,14 @@ started; for instance, <code>os.Args</code> is a slice used by the
|
||||
<p>
|
||||
Go has some familiar types such as <code>int</code> and <code>float</code>, which represent
|
||||
values of the ''appropriate'' size for the machine. It also defines
|
||||
specifically-sized types such as <code>int8</code>, <code>float64</code>, and so on, plus
|
||||
explicitly-sized types such as <code>int8</code>, <code>float64</code>, and so on, plus
|
||||
unsigned integer types such as <code>uint</code>, <code>uint32</code>, etc. These are
|
||||
distinct types; even if <code>int</code> and <code>int32</code> are both 32 bits in size,
|
||||
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.
|
||||
<p>
|
||||
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
|
||||
of course you can change a string <i>variable</i> simply by
|
||||
reassigning it. This snippet from <code>strings.go</code> is legal code:
|
||||
@ -302,8 +303,11 @@ and invoke it like this:
|
||||
<p>
|
||||
Note how the return type (<code>int</code>) is defined for <code>sum()</code> by stating it
|
||||
after the parameter list.
|
||||
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>
|
||||
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>
|
||||
in front gives us the address of a unique instance of the value. We pass the
|
||||
pointer to <code>sum()</code> by (implicitly) promoting it to a slice.
|
||||
<p>
|
||||
@ -315,7 +319,8 @@ elements for you, use <code>...</code> as the array size:
|
||||
</pre>
|
||||
<p>
|
||||
In practice, though, unless you're meticulous about storage layout within a
|
||||
data structure, a slice itself - using empty brackets and no <code>&</code> - is all you need:
|
||||
data structure, a slice itself—using empty brackets and no
|
||||
<code>&</code>—is all you need:
|
||||
<p>
|
||||
<pre>
|
||||
s := sum([]int{1,2,3});
|
||||
@ -351,7 +356,7 @@ or the more idiomatic
|
||||
t := new(T);
|
||||
</pre>
|
||||
<p>
|
||||
Some types - maps, slices, and channels (see below) - have reference semantics.
|
||||
Some types—maps, slices, and channels (see below)—have reference semantics.
|
||||
If you're holding a slice or a map and you modify its contents, other variables
|
||||
referencing the same underlying data will see the modification. For these three
|
||||
types you want to use the built-in function <code>make()</code>:
|
||||
@ -368,12 +373,12 @@ If you just declare the map, as in
|
||||
</pre>
|
||||
<p>
|
||||
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 of an
|
||||
you must first initialize the reference using <code>make()</code> or by assignment from an
|
||||
existing map.
|
||||
<p>
|
||||
Note that <code>new(T)</code> returns type <code>*T</code> while <code>make(T)</code> returns type
|
||||
<code>T</code>. If you (mistakenly) allocate a reference object with <code>new()</code>,
|
||||
you receive a pointer to an uninitialized reference, equivalent to
|
||||
you receive a pointer to a nil reference, equivalent to
|
||||
declaring an uninitialized variable and taking its address.
|
||||
<p>
|
||||
<h2>An Interlude about Constants</h2>
|
||||
@ -393,7 +398,7 @@ language specification but here are some illustrative examples:
|
||||
<p>
|
||||
<pre>
|
||||
var a uint64 = 0 // a has type uint64, value 0
|
||||
a := uint64(0) // equivalent; use a "conversion"
|
||||
a := uint64(0) // equivalent; uses a "conversion"
|
||||
i := 0x1234 // i gets default type: int
|
||||
var j int = 1e6 // legal - 1000000 is representable in an int
|
||||
x := 1.5 // a float
|
||||
@ -426,8 +431,9 @@ sort of open/close/read/write interface. Here's the start of <code>file.go</cod
|
||||
15 }
|
||||
</pre>
|
||||
<p>
|
||||
The first few lines declare the name of the package - <code>file</code> -
|
||||
and then import two packages. The <code>os</code> package hides the differences
|
||||
The first few lines declare the name of the
|
||||
package—<code>file</code>—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
|
||||
so on; here we're going to use its error handling utilities
|
||||
and reproduce the rudiments of its file I/O.
|
||||
@ -671,7 +677,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
|
||||
they all have the same type.
|
||||
<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
|
||||
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
|
||||
@ -695,8 +701,8 @@ Here is code from <code>progs/cat_rot13.go</code>:
|
||||
29 }
|
||||
</pre>
|
||||
<p>
|
||||
Any type that has the two methods of <code>reader</code> - regardless of whatever
|
||||
other methods the type may also have - is said to <i>implement</i> the
|
||||
Any type that has the two methods of <code>reader</code>—regardless of whatever
|
||||
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
|
||||
<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
|
||||
@ -1011,7 +1017,7 @@ operations such as type conversion, map update, communications, and so on,
|
||||
although this is the only appearance in this tutorial.)
|
||||
If the value does not satisfy the interface, <code>ok</code> will be false.
|
||||
<p>
|
||||
In this snippet the name <code>Stringer</code> follows the convention that we add <code>[e]r</code>
|
||||
In this snippet the name <code>Stringer</code> follows the convention that we add ''[e]r''
|
||||
to interfaces describing simple method sets like this.
|
||||
<p>
|
||||
One last wrinkle. To complete the suite, besides <code>Printf</code> etc. and <code>Sprintf</code>
|
||||
@ -1033,11 +1039,11 @@ you want.
|
||||
<p>
|
||||
<h2>Prime numbers</h2>
|
||||
<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.
|
||||
<p>
|
||||
A classic program in the style is a prime sieve.
|
||||
(The sieve of Eratosthenes is computationationally more efficient than
|
||||
(The sieve of Eratosthenes is computationally more efficient than
|
||||
the algorithm presented here, but we are more interested in concurrency than
|
||||
algorithmics at the moment.)
|
||||
It works by taking a stream of all the natural numbers and introducing
|
||||
@ -1099,7 +1105,7 @@ operator <code><-</code> (receive) retrieves the next value on the channel.
|
||||
<p>
|
||||
The generator and filters execute concurrently. Go has
|
||||
its own model of process/threads/light-weight processes/coroutines,
|
||||
so to avoid notational confusion we'll call concurrently executing
|
||||
so to avoid notational confusion we call concurrently executing
|
||||
computations in Go <i>goroutines</i>. To start a goroutine,
|
||||
invoke the function, prefixing the call with the keyword <code>go</code>;
|
||||
this starts the function running in parallel with the current
|
||||
|
@ -25,12 +25,13 @@ Let's start in the usual way:
|
||||
--PROG progs/helloworld.go /package/ END
|
||||
|
||||
Every Go source file declares, using a "package" statement, which package it's part of.
|
||||
The "main" package's "main" function is where the program starts running (after
|
||||
any initialization). It may also import other packages to use their facilities.
|
||||
It may also import other packages to use their facilities.
|
||||
This program imports the package "fmt" to gain access to
|
||||
our old, now capitalized and package-qualified friend, "fmt.Printf".
|
||||
our old, now capitalized and package-qualified, friend, "fmt.Printf".
|
||||
|
||||
Function declarations are introduced with the "func" keyword.
|
||||
Functions are introduced with the "func" keyword.
|
||||
The "main" package's "main" function is where the program starts running (after
|
||||
any initialization).
|
||||
|
||||
String constants can contain Unicode characters, encoded in UTF-8.
|
||||
(In fact, Go source files are defined to be encoded in UTF-8.)
|
||||
@ -86,7 +87,7 @@ But it's not necessary to do so; we could have said
|
||||
const Newline = "\n"
|
||||
|
||||
Semicolons aren't needed here; in fact, semicolons are unnecessary after any
|
||||
top-level declaration, even though they are needed as separators <i>within</i>
|
||||
top-level declaration, although they are needed as separators <i>within</i>
|
||||
a parenthesized list of declarations.
|
||||
|
||||
This program imports the ""os"" package to access its "Stdout" variable, of type
|
||||
@ -163,14 +164,14 @@ An Interlude about Types
|
||||
|
||||
Go has some familiar types such as "int" and "float", which represent
|
||||
values of the ''appropriate'' size for the machine. It also defines
|
||||
specifically-sized types such as "int8", "float64", and so on, plus
|
||||
explicitly-sized types such as "int8", "float64", and so on, plus
|
||||
unsigned integer types such as "uint", "uint32", etc. These are
|
||||
distinct types; even if "int" and "int32" are both 32 bits in size,
|
||||
they are not the same type. There is also a "byte" synonym for
|
||||
"uint8", which is the element type for strings.
|
||||
|
||||
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
|
||||
of course you can change a string <i>variable</i> simply by
|
||||
reassigning it. This snippet from "strings.go" is legal code:
|
||||
@ -232,8 +233,11 @@ and invoke it like this:
|
||||
|
||||
Note how the return type ("int") is defined for "sum()" by stating it
|
||||
after the parameter list.
|
||||
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 "&"
|
||||
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 "&"
|
||||
in front gives us the address of a unique instance of the value. We pass the
|
||||
pointer to "sum()" by (implicitly) promoting it to a slice.
|
||||
|
||||
@ -243,7 +247,8 @@ elements for you, use "..." as the array size:
|
||||
s := sum(&[...]int{1,2,3});
|
||||
|
||||
In practice, though, unless you're meticulous about storage layout within a
|
||||
data structure, a slice itself - using empty brackets and no "&" - is all you need:
|
||||
data structure, a slice itself—using empty brackets and no
|
||||
"&"—is all you need:
|
||||
|
||||
s := sum([]int{1,2,3});
|
||||
|
||||
@ -272,7 +277,7 @@ or the more idiomatic
|
||||
|
||||
t := new(T);
|
||||
|
||||
Some types - maps, slices, and channels (see below) - have reference semantics.
|
||||
Some types—maps, slices, and channels (see below)—have reference semantics.
|
||||
If you're holding a slice or a map and you modify its contents, other variables
|
||||
referencing the same underlying data will see the modification. For these three
|
||||
types you want to use the built-in function "make()":
|
||||
@ -285,12 +290,12 @@ If you just declare the map, as in
|
||||
var m map[string]int;
|
||||
|
||||
it creates a "nil" reference that cannot hold anything. To use the map,
|
||||
you must first initialize the reference using "make()" or by assignment of an
|
||||
you must first initialize the reference using "make()" or by assignment from an
|
||||
existing map.
|
||||
|
||||
Note that "new(T)" returns type "*T" while "make(T)" returns type
|
||||
"T". If you (mistakenly) allocate a reference object with "new()",
|
||||
you receive a pointer to an uninitialized reference, equivalent to
|
||||
you receive a pointer to a nil reference, equivalent to
|
||||
declaring an uninitialized variable and taking its address.
|
||||
|
||||
An Interlude about Constants
|
||||
@ -308,7 +313,7 @@ There are nuances that deserve redirection to the legalese of the
|
||||
language specification but here are some illustrative examples:
|
||||
|
||||
var a uint64 = 0 // a has type uint64, value 0
|
||||
a := uint64(0) // equivalent; use a "conversion"
|
||||
a := uint64(0) // equivalent; uses a "conversion"
|
||||
i := 0x1234 // i gets default type: int
|
||||
var j int = 1e6 // legal - 1000000 is representable in an int
|
||||
x := 1.5 // a float
|
||||
@ -329,8 +334,9 @@ sort of open/close/read/write interface. Here's the start of "file.go":
|
||||
|
||||
--PROG progs/file.go /package/ /^}/
|
||||
|
||||
The first few lines declare the name of the package - "file" -
|
||||
and then import two packages. The "os" package hides the differences
|
||||
The first few lines declare the name of the
|
||||
package—"file"—and then import two packages. The "os"
|
||||
package hides the differences
|
||||
between various operating systems to give a consistent view of files and
|
||||
so on; here we're going to use its error handling utilities
|
||||
and reproduce the rudiments of its file I/O.
|
||||
@ -451,7 +457,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
|
||||
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
|
||||
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
|
||||
@ -470,8 +476,8 @@ Here is code from "progs/cat_rot13.go":
|
||||
|
||||
--PROG progs/cat_rot13.go /type.reader/ /^}/
|
||||
|
||||
Any type that has the two methods of "reader" - regardless of whatever
|
||||
other methods the type may also have - is said to <i>implement</i> the
|
||||
Any type that has the two methods of "reader"—regardless of whatever
|
||||
other methods the type may also have—is said to <i>implement</i> the
|
||||
interface. Since "file.File" implements these methods, it implements the
|
||||
"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
|
||||
@ -665,7 +671,7 @@ operations such as type conversion, map update, communications, and so on,
|
||||
although this is the only appearance in this tutorial.)
|
||||
If the value does not satisfy the interface, "ok" will be false.
|
||||
|
||||
In this snippet the name "Stringer" follows the convention that we add "[e]r"
|
||||
In this snippet the name "Stringer" follows the convention that we add ''[e]r''
|
||||
to interfaces describing simple method sets like this.
|
||||
|
||||
One last wrinkle. To complete the suite, besides "Printf" etc. and "Sprintf"
|
||||
@ -686,11 +692,11 @@ you want.
|
||||
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.
|
||||
|
||||
A classic program in the style is a prime sieve.
|
||||
(The sieve of Eratosthenes is computationationally more efficient than
|
||||
(The sieve of Eratosthenes is computationally more efficient than
|
||||
the algorithm presented here, but we are more interested in concurrency than
|
||||
algorithmics at the moment.)
|
||||
It works by taking a stream of all the natural numbers and introducing
|
||||
@ -734,7 +740,7 @@ operator "<-" (receive) retrieves the next value on the channel.
|
||||
|
||||
The generator and filters execute concurrently. Go has
|
||||
its own model of process/threads/light-weight processes/coroutines,
|
||||
so to avoid notational confusion we'll call concurrently executing
|
||||
so to avoid notational confusion we call concurrently executing
|
||||
computations in Go <i>goroutines</i>. To start a goroutine,
|
||||
invoke the function, prefixing the call with the keyword "go";
|
||||
this starts the function running in parallel with the current
|
||||
|
Loading…
Reference in New Issue
Block a user