mirror of
https://github.com/golang/go
synced 2024-11-21 17:34:40 -07:00
remove print() from the tutorial, generating a little clumsiness around "import"
R=rsc,gri DELTA=103 (36 added, 33 deleted, 34 changed) OCL=26442 CL=26491
This commit is contained in:
parent
08eeb2535d
commit
bdbb3b455e
@ -4,7 +4,7 @@ Let's Go
|
||||
Rob Pike
|
||||
|
||||
----
|
||||
(March 17, 2009)
|
||||
(March 18, 2009)
|
||||
|
||||
|
||||
This document is a tutorial introduction to the basics of the Go systems programming
|
||||
@ -36,7 +36,9 @@ Let's start in the usual way:
|
||||
|
||||
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).
|
||||
any initialization). 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".
|
||||
|
||||
Function declarations are introduced with the "func" keyword.
|
||||
|
||||
@ -44,18 +46,6 @@ Notice that 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
|
||||
to store Unicode strings represented in UTF-8.
|
||||
|
||||
The built-in function "print()" has been used during the early stages of
|
||||
development of the language but is not guaranteed to last. Here's a version of the
|
||||
program that doesn't depend on "print()":
|
||||
|
||||
--PROG progs/helloworld2.go
|
||||
|
||||
This version imports the ''os'' package to acess its "Stdout" variable, of type
|
||||
"*os.File". The "import" statement is a declaration: it names the identifier ("os")
|
||||
that will be used to access members of the package imported from the file ("os"),
|
||||
found in the current directory or in a standard location.
|
||||
Given "os.Stdout" we can use its "WriteString" method to print the string.
|
||||
|
||||
The comment convention is the same as in C++:
|
||||
|
||||
/* ... */
|
||||
@ -84,12 +74,23 @@ 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>
|
||||
a parenthesized list of declarations.
|
||||
|
||||
Also notice that we've dropped the explicit name from the imports; by default,
|
||||
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,
|
||||
as used in our ``hello world'' program,
|
||||
it names the identifier ("fmt")
|
||||
that will be used to access members of the package imported from the file (""fmt""),
|
||||
found in the current directory or in a standard location.
|
||||
In this program, though, we've dropped the explicit name from the imports; by default,
|
||||
packages are imported using the name defined by the imported package,
|
||||
which by convention is of course the file name itself. You can specify your
|
||||
which by convention is of course the file name itself. Our ``hello world'' program
|
||||
could have said just "import "fmt"".
|
||||
|
||||
You can specify your
|
||||
own import names if you want but it's only necessary if you need to resolve
|
||||
a naming conflict.
|
||||
|
||||
Given "os.Stdout" we can use its "WriteString" method to print the string.
|
||||
|
||||
Having imported the "flag" package, line 8 creates a global variable to hold
|
||||
the value of echo's "-n" flag. The variable "n_flag" has type "*bool", pointer
|
||||
to "bool".
|
||||
@ -407,7 +408,7 @@ Finally, we can use our new package:
|
||||
|
||||
--PROG progs/helloworld3.go
|
||||
|
||||
and run the program:
|
||||
And now we can run the program:
|
||||
|
||||
% helloworld3
|
||||
hello, world
|
||||
@ -424,8 +425,8 @@ Building on the "file" package, here's a simple version of the Unix utility "cat
|
||||
|
||||
By now this should be easy to follow, but the "switch" statement introduces some
|
||||
new features. Like a "for" loop, an "if" or "switch" can include an
|
||||
initialization statement. The "switch" on line 12 uses one to create variables
|
||||
"nr" and "er" to hold the return values from "f.Read()". (The "if" on line 19
|
||||
initialization statement. The "switch" on line 14 uses one to create variables
|
||||
"nr" and "er" to hold the return values from "f.Read()". (The "if" on line 21
|
||||
has the same idea.) The "switch" statement is general: it evaluates the cases
|
||||
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
|
||||
@ -437,7 +438,7 @@ 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
|
||||
"switch" statements each "case" has an implicit "break".
|
||||
|
||||
Line 19 calls "Write()" by slicing the incoming buffer, which is itself a slice.
|
||||
Line 21 calls "Write()" by slicing the incoming buffer, which is itself a slice.
|
||||
Slices provide the standard Go way to handle I/O buffers.
|
||||
|
||||
Now let's make a variant of "cat" that optionally does "rot13" on its input.
|
||||
@ -462,7 +463,7 @@ we have a second implementation of the "reader" interface.
|
||||
|
||||
--PROG progs/cat_rot13.go /type.rotate13/ /end.of.rotate13/
|
||||
|
||||
(The "rot13" function called on line 37 is trivial and not worth reproducing.)
|
||||
(The "rot13" function called on line 38 is trivial and not worth reproducing.)
|
||||
|
||||
To use the new feature, we define a flag:
|
||||
|
||||
@ -474,7 +475,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 51 through 53 set it all up: If the "rot13" flag is true, wrap the "reader"
|
||||
Lines 52 through 55 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".
|
||||
@ -551,11 +552,8 @@ Printing
|
||||
The examples of formatted printing so far have been modest. In this section
|
||||
we'll talk about how formatted I/O can be done well in Go.
|
||||
|
||||
There's a package "fmt" that implements a version of "Printf" (upper case)
|
||||
that should look familiar:
|
||||
|
||||
--PROG progs/printf.go
|
||||
|
||||
We've seen simple uses of the package "fmt", which
|
||||
implements "Printf", "Fprintf", and so on.
|
||||
Within the "fmt" package, "Printf" is declared with this signature:
|
||||
|
||||
Printf(format string, v ...) (n int, errno *os.Error)
|
||||
@ -740,7 +738,7 @@ together:
|
||||
|
||||
--PROG progs/sieve.go /func.main/ /^}/
|
||||
|
||||
Line 23 creates the initial channel to pass to "generate", which it
|
||||
Line 25 creates the initial channel to pass to "generate", which it
|
||||
then starts up. As each prime pops out of the channel, a new "filter"
|
||||
is added to the pipeline and <i>its</i> output becomes the new value
|
||||
of "ch".
|
||||
@ -756,7 +754,7 @@ channel, launches a goroutine internally using a function literal, and
|
||||
returns the channel to the caller. It is a factory for concurrent
|
||||
execution, starting the goroutine and returning its connection.
|
||||
|
||||
The function literal notation (lines 6-10) allows us to construct an
|
||||
The function literal notation (lines 8-12) allows us to construct an
|
||||
anonymous function and invoke it on the spot.
|
||||
|
||||
The same change can be made to "filter":
|
||||
@ -789,7 +787,7 @@ code that invokes the operation and responds to the request:
|
||||
|
||||
--PROG progs/server.go /type.binOp/ /^}/
|
||||
|
||||
Line 8 defines the name "binOp" to be a function taking two integers and
|
||||
Line 10 defines the name "binOp" to be a function taking two integers and
|
||||
returning a third.
|
||||
|
||||
The "server" routine loops forever, receiving requests and, to avoid blocking due to
|
||||
|
@ -7,6 +7,8 @@ package main
|
||||
import (
|
||||
"file";
|
||||
"flag";
|
||||
"fmt";
|
||||
"os";
|
||||
)
|
||||
|
||||
func cat(f *file.File) {
|
||||
@ -15,13 +17,13 @@ func cat(f *file.File) {
|
||||
for {
|
||||
switch nr, er := f.Read(buf); true {
|
||||
case nr < 0:
|
||||
print("error reading from ", f.String(), ": ", er.String(), "\n");
|
||||
fmt.Fprintf(os.Stderr, "error reading from %s: %s\n", f.String(), er.String());
|
||||
sys.Exit(1);
|
||||
case nr == 0: // EOF
|
||||
return;
|
||||
case nr > 0:
|
||||
if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
|
||||
print("error writing from ", f.String(), ": ", ew.String(), "\n");
|
||||
fmt.Fprintf(os.Stderr, "error writing from %s: %s\n", f.String(), ew.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,7 +37,7 @@ func main() {
|
||||
for i := 0; i < flag.NArg(); i++ {
|
||||
f, err := file.Open(flag.Arg(i), 0, 0);
|
||||
if f == nil {
|
||||
print("can't open ", flag.Arg(i), ": error ", err, "\n");
|
||||
fmt.Fprintf(os.Stderr, "can't open %s: error %s\n", flag.Arg(i), err);
|
||||
sys.Exit(1);
|
||||
}
|
||||
cat(f);
|
||||
|
@ -7,6 +7,7 @@ package main
|
||||
import (
|
||||
"file";
|
||||
"flag";
|
||||
"fmt";
|
||||
"os";
|
||||
)
|
||||
|
||||
@ -58,14 +59,14 @@ func cat(r reader) {
|
||||
for {
|
||||
switch nr, er := r.Read(buf); {
|
||||
case nr < 0:
|
||||
print("error reading from ", r.String(), ": ", er.String(), "\n");
|
||||
fmt.Fprintf(os.Stderr, "error reading from %s: %s\n", r.String(), er.String());
|
||||
sys.Exit(1);
|
||||
case nr == 0: // EOF
|
||||
return;
|
||||
case nr > 0:
|
||||
nw, ew := file.Stdout.Write(buf[0:nr]);
|
||||
if nw != nr {
|
||||
print("error writing from ", r.String(), ": ", ew.String(), "\n");
|
||||
fmt.Fprintf(os.Stderr, "error writing from %s: %s\n", r.String(), ew.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,7 +80,7 @@ func main() {
|
||||
for i := 0; i < flag.NArg(); i++ {
|
||||
f, err := file.Open(flag.Arg(i), 0, 0);
|
||||
if f == nil {
|
||||
print("can't open ", flag.Arg(i), ": error ", err, "\n");
|
||||
fmt.Fprintf(os.Stderr, "can't open %s: error %s\n", flag.Arg(i), err);
|
||||
sys.Exit(1);
|
||||
}
|
||||
cat(f);
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import fmt "fmt" // Package implementing formatted I/O.
|
||||
|
||||
func main() {
|
||||
print("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
|
||||
fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import os "os" // this package contains features for basic I/O
|
||||
|
||||
func main() {
|
||||
os.Stdout.WriteString("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
|
||||
}
|
@ -4,14 +4,17 @@
|
||||
|
||||
package main
|
||||
|
||||
import file "file"
|
||||
import (
|
||||
"file";
|
||||
"fmt";
|
||||
)
|
||||
|
||||
func main() {
|
||||
hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'};
|
||||
file.Stdout.Write(hello);
|
||||
file, err := file.Open("/does/not/exist", 0, 0);
|
||||
if file == nil {
|
||||
print("can't open file; err=", err.String(), "\n");
|
||||
fmt.Printf("can't open file; err=%s\n", err.String());
|
||||
sys.Exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("hello, %s\n", "world");
|
||||
}
|
@ -8,7 +8,6 @@ rm -f *.6
|
||||
for i in \
|
||||
file.go \
|
||||
helloworld.go \
|
||||
helloworld2.go \
|
||||
helloworld3.go \
|
||||
echo.go \
|
||||
cat.go \
|
||||
@ -17,7 +16,6 @@ for i in \
|
||||
sort.go \
|
||||
sortmain.go \
|
||||
print.go \
|
||||
printf.go \
|
||||
print_string.go \
|
||||
sieve.go \
|
||||
sieve1.go \
|
||||
@ -48,7 +46,6 @@ function testitpipe {
|
||||
|
||||
|
||||
testit helloworld "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
|
||||
testit helloworld2 "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
|
||||
testit helloworld3 "" "hello, world can't open file; err=No such file or directory"
|
||||
testit echo "hello, world" "hello, world"
|
||||
testit sum "" "6"
|
||||
@ -62,7 +59,6 @@ echo $rot13 | testit cat_rot13 "--rot13" $alphabet
|
||||
testit sortmain "" "Sunday Monday Tuesday Thursday Friday"
|
||||
|
||||
testit print "" "18446744073709551615 -1 18446744073709551615 {77 Sunset Strip} [1 2 3 4] 18446744073709551615 {77 Sunset Strip} [1 2 3 4] 18446744073709551615 {77 Sunset Strip} [1 2 3 4]"
|
||||
testit printf "" "hello, world"
|
||||
testit print_string "" "77 Sunset Strip"
|
||||
|
||||
testitpipe sieve "sed 10q" "2 3 5 7 11 13 17 19 23 29"
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type request struct {
|
||||
a, b int;
|
||||
replyc chan int;
|
||||
@ -42,8 +44,8 @@ func main() {
|
||||
}
|
||||
for i := N-1; i >= 0; i-- { // doesn't matter what order
|
||||
if <-reqs[i].replyc != N + 2*i {
|
||||
print("fail at ", i, "\n");
|
||||
fmt.Println("fail at", i);
|
||||
}
|
||||
}
|
||||
print("done\n");
|
||||
fmt.Println("done");
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type request struct {
|
||||
a, b int;
|
||||
replyc chan int;
|
||||
@ -47,7 +49,7 @@ func main() {
|
||||
}
|
||||
for i := N-1; i >= 0; i-- { // doesn't matter what order
|
||||
if <-reqs[i].replyc != N + 2*i {
|
||||
print("fail at ", i, "\n");
|
||||
fmt.Println("fail at", i);
|
||||
}
|
||||
}
|
||||
quit <- true;
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Send the sequence 2, 3, 4, ... to channel 'ch'.
|
||||
func generate(ch chan int) {
|
||||
for i := 2; ; i++ {
|
||||
@ -28,7 +30,7 @@ func main() {
|
||||
go generate(ch); // Start generate() as a goroutine.
|
||||
for {
|
||||
prime := <-ch;
|
||||
print(prime, "\n");
|
||||
fmt.Println(prime);
|
||||
ch1 := make(chan int);
|
||||
go filter(ch, ch1, prime);
|
||||
ch = ch1
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Send the sequence 2, 3, 4, ... to returned channel
|
||||
func generate() chan int {
|
||||
ch := make(chan int);
|
||||
@ -44,6 +46,6 @@ func sieve() chan int {
|
||||
func main() {
|
||||
primes := sieve();
|
||||
for {
|
||||
print(<-primes, "\n");
|
||||
fmt.Println(<-primes);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "sort"
|
||||
import (
|
||||
"fmt";
|
||||
"sort";
|
||||
)
|
||||
|
||||
func ints() {
|
||||
data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586};
|
||||
@ -53,9 +56,9 @@ func days() {
|
||||
panic()
|
||||
}
|
||||
for i, d := range data {
|
||||
print(d.long_name, " ")
|
||||
fmt.Printf("%s ", d.long_name)
|
||||
}
|
||||
print("\n")
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
s := "hello";
|
||||
if s[1] == 'e' { print("success") }
|
||||
if s[1] != 'e' { sys.Exit(1) }
|
||||
s = "good bye";
|
||||
var p *string = &s;
|
||||
*p = "ciao";
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func sum(a []int) int { // returns an int
|
||||
s := 0;
|
||||
for i := 0; i < len(a); i++ {
|
||||
@ -15,5 +17,5 @@ func sum(a []int) int { // returns an int
|
||||
|
||||
func main() {
|
||||
s := sum([3]int{1,2,3}); // a slice of the array is passed to sum
|
||||
print(s, "\n");
|
||||
fmt.Print(s, "\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user