diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html index 91bee3fa85..c1f3b04d24 100644 --- a/doc/go_tutorial.html +++ b/doc/go_tutorial.html @@ -1,12 +1,15 @@
-This document is a tutorial introduction to the basics of the Go systems programming +This document is a tutorial introduction to the basics of the Go programming language, intended for programmers familiar with C or C++. It is not a comprehensive guide to the language; at the moment the document closest to that is the -language specification. +language specification. +After you've read this tutorial, you might want to look at +Effective Go, +which digs deeper into how the language is used.
-The presentation proceeds through a series of modest programs to illustrate
+The presentation here proceeds through a series of modest programs to illustrate
key features of the language. All the programs work (at time of writing) and are
checked into the repository in the directory /doc/progs/
.
@@ -48,6 +51,35 @@ The comment convention is the same as in C++:
Later we'll have much more to say about printing.
+
+Go is a compiled language. At the moment there are two compilers.
+Gccgo
is a Go compiler that uses the GCC back end. There is also a
+suite of compilers with different (and odd) names for each architecture:
+6g
for the 64-bit x86, 8g
for the 32-bit x86, and more. These
+compilers run significantly faster but generate less efficient code
+than gccgo
. At the time of writing (late 2009), they also have
+a more robust run-time system although gccgo
is catching up.
+
+Here's how to compile and run our program. With 6g
, say,
+
+
+ $ 6g helloworld.go # compile; object goes into helloworld.6 + $ 6l helloworld.6 # link; output goes into 6.out + $ 6.out + Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 + $ ++
+With gccgo
it looks a little more traditional.
+
+
+ $ gccgo helloworld.go + $ a.out + Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 + $ ++
Next up, here's a version of the Unix utility echo(1)
:
@@ -63,8 +95,8 @@ Next up, here's a version of the Unix utility echo(1)
:
12 var n_flag = flag.Bool("n", false, "don't print final newline")
14 const ( -15 kSpace = " "; -16 kNewline = "\n"; +15 Space = " "; +16 Newline = "\n"; 17 )
19 func main() {
@@ -72,22 +104,22 @@ Next up, here's a version of the Unix utility echo(1)
:
21 var s string = "";
22 for i := 0; i < flag.NArg(); i++ {
23 if i > 0 {
-24 s += kSpace
+24 s += Space
25 }
26 s += flag.Arg(i)
27 }
28 if !*n_flag {
-29 s += kNewline
+29 s += Newline
30 }
31 os.Stdout.WriteString(s);
32 }
This program is small but it's doing a number of new things. In the last example,
-we saw func
introducing 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
.
Notice that we can group declarations of the same sort into
-parenthesized, semicolon-separated lists if we want, as on lines 4-10 and 14-17.
+parenthesized, semicolon-separated lists if we want, as on lines 7-10 and 14-17.
But it's not necessary to do so; we could have said
@@ -168,7 +200,7 @@ Later examples will show some other waysfor
can be written.The body of the loop builds up the string
s
by appending (using+=
) the flags and separating spaces. After the loop, if the-n
flag is not -set, it appends a newline, and then writes the result. +set, the program appends a newline. Finally, it writes the result.Notice that
main.main
is a niladic function with no return type. It's defined that way. Falling off the end ofmain.main
means @@ -234,7 +266,7 @@ about pointers to arrays. The size of the array is part of its type; however, one can declare a slice variable, to which one can assign a pointer to any array -with the same element type or - much more commonly - a slice +with the same element type or—much more commonly—a slice expression of the forma[low : high]
, representing the subarray indexed bylow
throughhigh-1
. Slices look a lot like arrays but have @@ -276,7 +308,7 @@ and invoke it like this: Note how the return type (int
) is defined forsum()
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 3ints
. Putting an&
+-- is a constructor for a value, in this case an array of 3ints
. Putting an&
in front gives us the address of a unique instance of the value. We pass the pointer tosum()
by (automatically) promoting it to a slice.@@ -288,7 +320,7 @@ elements for you, use
...
as the array size:
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}); @@ -297,7 +329,7 @@ data structure, a slice itself - using empty brackets and no@@ -415,8 +447,8 @@ that the file descriptor refers to.&
- is There are also maps, which you can initialize like this:
- m := map[string] int {"one":1 , "two":2} + m := map[string]int{"one":1 , "two":2}The built-in function
len()
, which returns number of elements, @@ -330,14 +362,14 @@ referencing the same underlying data will see the modification. For these three types you want to use the built-in functionmake()
:
- m := make(map[string] int); + m := make(map[string]int);This statement initializes a new map ready to store entries. 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, @@ -352,7 +384,7 @@ declaring an uninitialized variable and taking its address.An Interlude about Constants
Although integers come in lots of sizes in Go, integer constants do not. -There are no constants like
0ll
or0x0UL
. Instead, integer +There are no constants like0LL
or0x0UL
. Instead, integer constants are evaluated as large-precision values that can overflow only when they are assigned to an integer variable with too little precision to represent the value. @@ -394,7 +426,7 @@ sort of open/close/read/write interface. Here's the start offile.go 12 type File struct { -13 fd int; // file descriptor number +13 fd int; // file descriptor number 14 name string; // file name at Open time 15 }
Because File
starts with a capital letter, the type is available outside the package,
that is, by users of the package. In Go the rule about visibility of information is
-simple: if a name (of a top-level type, function, method, constant, variable, or of
-a structure field) is capitalized, users of the package may see it. Otherwise, the
+simple: if a name (of a top-level type, function, method, constant or variable, or of
+a structure field or method) is capitalized, users of the package may see it. Otherwise, the
name and hence the thing being named is visible only inside the package in which
it is declared. This is more than a convention; the rule is enforced by the compiler.
In Go, the term for publicly visible names is ''exported''.
@@ -545,7 +577,7 @@ the struct
declaration itself. The struct
declaration
In fact, methods can be created for any type you name, such as an integer or
array, not just for structs
. We'll see an example with arrays later.
-The String
method is so called because of printing convention we'll
+The String
method is so called because of a printing convention we'll
describe later.
The methods use the public variable os.EINVAL
to return the (os.Error
@@ -607,13 +639,13 @@ Building on the file
package, here's a simple version of the Unix u
17 for {
18 switch nr, er := f.Read(&buf); true {
19 case nr < 0:
-20 fmt.Fprintf(os.Stderr, "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);
22 case nr == 0: // EOF
23 return;
24 case nr > 0:
25 if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
-26 fmt.Fprintf(os.Stderr, "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 }
28 }
29 }
@@ -627,7 +659,7 @@ Building on the file
package, here's a simple version of the Unix u
37 for i := 0; i < flag.NArg(); i++ {
38 f, err := file.Open(flag.Arg(i), 0, 0);
39 if f == nil {
-40 fmt.Fprintf(os.Stderr, "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);
42 }
43 cat(f);
@@ -702,7 +734,7 @@ we have a second implementation of the reader
interface.
50 // end of rotate13 implementation
-(The rot13
function called on line 42 is trivial and not worth reproducing.)
+(The rot13
function called on line 42 is trivial and not worth reproducing here.)
To use the new feature, we define a flag:
@@ -723,14 +755,14 @@ and use it from within a mostly unchanged cat()
function:
59 for {
60 switch nr, er := r.Read(&buf); {
61 case nr < 0:
-62 fmt.Fprintf(os.Stderr, "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);
64 case nr == 0: // EOF
65 return;
66 case nr > 0:
67 nw, ew := file.Stdout.Write(buf[0:nr]);
68 if nw != nr {
-69 fmt.Fprintf(os.Stderr, "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 }
71 }
72 }
@@ -739,7 +771,7 @@ and use it from within a mostly unchanged cat()
function:
(We could also do the wrapping in main
and leave cat()
mostly alone, except
for changing the type of the argument; consider that an exercise.)
-Lines 56 through 59 set it all up: If the rot13
flag is true, wrap the reader
+Lines 56 through 58 set it all up: If the rot13
flag is true, wrap the reader
we received into a rotate13
and proceed. Note that the interface variables
are values, not pointers: the argument is of type reader
, not *reader
,
even though under the covers it holds a pointer to a struct
.
@@ -838,8 +870,8 @@ to implement the three methods for that type, like this:
30 type day struct { 31 num int; -32 short_name string; -33 long_name string; +32 shortName string; +33 longName string; 34 }36 type dayArray struct { @@ -972,7 +1004,7 @@ Schematically, given a value
v
, it does this: if ok { result = s.String() } else { - result = default_output(v) + result = defaultOutput(v) }
@@ -1002,7 +1034,7 @@ interface type defined in the io
library:
(This interface is another conventional name, this time for Write
; there are also
io.Reader
, io.ReadWriter
, and so on.)
Thus you can call Fprintf
on any type that implements a standard Write()
-method, not just files but also network channels, buffers, rot13ers, whatever
+method, not just files but also network channels, buffers, whatever
you want.
-A classic program in the style is the prime sieve of Eratosthenes. +A classic program in the style is a prime sieve. +(The sieve of Eratosthenes is computationationally 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 a sequence of filters, one for each prime, to winnow the multiples of that prime. At each step we have a sequence of filters of the primes @@ -1310,6 +1345,3 @@ at the end of main:
There's a lot more to Go programming and concurrent programming in general but this quick tour should give you some of the basics. - -