mirror of
https://github.com/golang/go
synced 2024-11-24 21:10:04 -07:00
tutorial: remove all line numbers and references to them.
R=golang-dev, mikioh.mikioh, dsymonds CC=golang-dev https://golang.org/cl/4675070
This commit is contained in:
parent
ab3365d34e
commit
c17347eea9
@ -19,9 +19,6 @@ 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
|
key features of the language. All the programs work (at time of writing) and are
|
||||||
checked into the repository in the directory <a href='/doc/progs'><code>/doc/progs/</code></a>.
|
checked into the repository in the directory <a href='/doc/progs'><code>/doc/progs/</code></a>.
|
||||||
<p>
|
<p>
|
||||||
Program snippets are annotated with the line number in the original file; for
|
|
||||||
cleanliness, blank lines remain blank.
|
|
||||||
<p>
|
|
||||||
<h2>Hello, World</h2>
|
<h2>Hello, World</h2>
|
||||||
<p>
|
<p>
|
||||||
Let's start in the usual way:
|
Let's start in the usual way:
|
||||||
@ -29,7 +26,7 @@ Let's start in the usual way:
|
|||||||
<pre><!-- progs/helloworld.go /package/ $
|
<pre><!-- progs/helloworld.go /package/ $
|
||||||
-->package main
|
-->package main
|
||||||
|
|
||||||
import fmt "fmt" // Package implementing formatted I/O.
|
import fmt "fmt" // Package implementing formatted I/O.
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n")
|
fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n")
|
||||||
@ -121,18 +118,18 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"flag" // command line option parser
|
"flag" // command line option parser
|
||||||
)
|
)
|
||||||
|
|
||||||
var omitNewline = flag.Bool("n", false, "don't print final newline")
|
var omitNewline = flag.Bool("n", false, "don't print final newline")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Space = " "
|
Space = " "
|
||||||
Newline = "\n"
|
Newline = "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse() // Scans the arg list and sets up flags
|
flag.Parse() // Scans the arg list and sets up flags
|
||||||
var s string = ""
|
var s string = ""
|
||||||
for i := 0; i < flag.NArg(); i++ {
|
for i := 0; i < flag.NArg(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@ -176,12 +173,13 @@ a naming conflict.
|
|||||||
<p>
|
<p>
|
||||||
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
|
After importing the <code>flag</code> package, we use a <code>var</code> declaration
|
||||||
the value of echo's <code>-n</code> flag. The variable <code>omitNewline</code> has type <code>*bool</code>, pointer
|
to create and initialize a global variable, called <code>omitNewline</code>,
|
||||||
to <code>bool</code>.
|
to hold the value of echo's <code>-n</code> flag.
|
||||||
|
The variable has type <code>*bool</code>, pointer 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 (the call to <code>flag.Parse</code>) and then create a local
|
||||||
string variable we will use to build the output.
|
string variable with which to build the output.
|
||||||
<p>
|
<p>
|
||||||
The declaration statement has the form
|
The declaration statement has the form
|
||||||
<p>
|
<p>
|
||||||
@ -261,7 +259,9 @@ reassigning it. This snippet from <code>strings.go</code> is legal code:
|
|||||||
<p>
|
<p>
|
||||||
<pre><!-- progs/strings.go /hello/ /ciao/
|
<pre><!-- progs/strings.go /hello/ /ciao/
|
||||||
--> s := "hello"
|
--> s := "hello"
|
||||||
if s[1] != 'e' { os.Exit(1) }
|
if s[1] != 'e' {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
s = "good bye"
|
s = "good bye"
|
||||||
var p *string = &s
|
var p *string = &s
|
||||||
*p = "ciao"
|
*p = "ciao"
|
||||||
@ -540,7 +540,7 @@ return n
|
|||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
but for simple structures like <code>File</code> it's easier to return the address of a
|
but for simple structures like <code>File</code> it's easier to return the address of a
|
||||||
composite literal, as is done here on line 21.
|
composite literal, as is done here in the <code>return</code> statement from <code>newFile</code>.
|
||||||
<p>
|
<p>
|
||||||
We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
|
We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
|
||||||
<p>
|
<p>
|
||||||
@ -573,9 +573,9 @@ multi-value return as a parenthesized list of declarations; syntactically
|
|||||||
they look just like a second parameter list. The function
|
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 the first line; it declares <code>r</code> and <code>e</code> to hold the two values,
|
||||||
both of type <code>int</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, <code>OpenFile</code> 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>
|
||||||
@ -689,7 +689,7 @@ func main() {
|
|||||||
file.Stdout.Write(hello)
|
file.Stdout.Write(hello)
|
||||||
f, err := file.Open("/does/not/exist")
|
f, err := file.Open("/does/not/exist")
|
||||||
if f == nil {
|
if f == nil {
|
||||||
fmt.Printf("can't open file; err=%s\n", err.String())
|
fmt.Printf("can't open file; err=%s\n", err.String())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -938,9 +938,9 @@ arrays of integers, strings, etc.; here's the code for arrays of <code>int</code
|
|||||||
<pre><!-- progs/sort.go /type.*IntSlice/ /Swap/
|
<pre><!-- progs/sort.go /type.*IntSlice/ /Swap/
|
||||||
-->type IntSlice []int
|
-->type IntSlice []int
|
||||||
|
|
||||||
func (p IntSlice) Len() int { return len(p) }
|
func (p IntSlice) Len() int { return len(p) }
|
||||||
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
|
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
|
||||||
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Here we see methods defined for non-<code>struct</code> types. You can define methods
|
Here we see methods defined for non-<code>struct</code> types. You can define methods
|
||||||
@ -966,18 +966,18 @@ to implement the three methods for that type, like this:
|
|||||||
<p>
|
<p>
|
||||||
<pre><!-- progs/sortmain.go /type.day/ /Swap/
|
<pre><!-- progs/sortmain.go /type.day/ /Swap/
|
||||||
-->type day struct {
|
-->type day struct {
|
||||||
num int
|
num int
|
||||||
shortName string
|
shortName string
|
||||||
longName string
|
longName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type dayArray struct {
|
type dayArray struct {
|
||||||
data []*day
|
data []*day
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *dayArray) Len() int { return len(p.data) }
|
func (p *dayArray) Len() int { return len(p.data) }
|
||||||
func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num }
|
func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num }
|
||||||
func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] }
|
func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] }
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
<p>
|
<p>
|
||||||
@ -1013,7 +1013,7 @@ can just say <code>%d</code>; <code>Printf</code> knows the size and signedness
|
|||||||
integer and can do the right thing for you. The snippet
|
integer and can do the right thing for you. The snippet
|
||||||
<p>
|
<p>
|
||||||
<pre><!-- progs/print.go 10 11
|
<pre><!-- progs/print.go 10 11
|
||||||
--> var u64 uint64 = 1<<64-1
|
--> var u64 uint64 = 1<<64 - 1
|
||||||
fmt.Printf("%d %d\n", u64, int64(u64))
|
fmt.Printf("%d %d\n", u64, int64(u64))
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
@ -1183,7 +1183,7 @@ Here is the first function in <code>progs/sieve.go</code>:
|
|||||||
-->// Send the sequence 2, 3, 4, ... to channel 'ch'.
|
-->// Send the sequence 2, 3, 4, ... to channel 'ch'.
|
||||||
func generate(ch chan int) {
|
func generate(ch chan int) {
|
||||||
for i := 2; ; i++ {
|
for i := 2; ; i++ {
|
||||||
ch <- i // Send 'i' to channel 'ch'.
|
ch <- i // Send 'i' to channel 'ch'.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
@ -1203,9 +1203,9 @@ operator <code><-</code> (receive) retrieves the next value on the channel.
|
|||||||
// removing those divisible by 'prime'.
|
// removing those divisible by 'prime'.
|
||||||
func filter(in, out chan int, prime int) {
|
func filter(in, out chan int, prime int) {
|
||||||
for {
|
for {
|
||||||
i := <-in // Receive value of new variable 'i' from 'in'.
|
i := <-in // Receive value of new variable 'i' from 'in'.
|
||||||
if i % prime != 0 {
|
if i%prime != 0 {
|
||||||
out <- i // Send 'i' to channel 'out'.
|
out <- i // Send 'i' to channel 'out'.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1238,8 +1238,8 @@ together:
|
|||||||
<p>
|
<p>
|
||||||
<pre><!-- progs/sieve.go /func.main/ /^}/
|
<pre><!-- progs/sieve.go /func.main/ /^}/
|
||||||
-->func main() {
|
-->func main() {
|
||||||
ch := make(chan int) // Create a new channel.
|
ch := make(chan int) // Create a new channel.
|
||||||
go generate(ch) // Start generate() as a goroutine.
|
go generate(ch) // Start generate() as a goroutine.
|
||||||
for i := 0; i < 100; i++ { // Print the first hundred primes.
|
for i := 0; i < 100; i++ { // Print the first hundred primes.
|
||||||
prime := <-ch
|
prime := <-ch
|
||||||
fmt.Println(prime)
|
fmt.Println(prime)
|
||||||
@ -1262,7 +1262,7 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
|
|||||||
<pre><!-- progs/sieve1.go /func.generate/ /^}/
|
<pre><!-- progs/sieve1.go /func.generate/ /^}/
|
||||||
-->func generate() chan int {
|
-->func generate() chan int {
|
||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
go func(){
|
go func() {
|
||||||
for i := 2; ; i++ {
|
for i := 2; ; i++ {
|
||||||
ch <- i
|
ch <- i
|
||||||
}
|
}
|
||||||
@ -1288,7 +1288,7 @@ The same change can be made to <code>filter</code>:
|
|||||||
out := make(chan int)
|
out := make(chan int)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if i := <-in; i % prime != 0 {
|
if i := <-in; i%prime != 0 {
|
||||||
out <- i
|
out <- i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1337,8 +1337,8 @@ that will be used for the reply.
|
|||||||
<p>
|
<p>
|
||||||
<pre><!-- progs/server.go /type.request/ /^}/
|
<pre><!-- progs/server.go /type.request/ /^}/
|
||||||
-->type request struct {
|
-->type request struct {
|
||||||
a, b int
|
a, b int
|
||||||
replyc chan int
|
replyc chan int
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
@ -1364,7 +1364,7 @@ a long-running operation, starting a goroutine to do the actual work.
|
|||||||
-->func server(op binOp, service chan *request) {
|
-->func server(op binOp, service chan *request) {
|
||||||
for {
|
for {
|
||||||
req := <-service
|
req := <-service
|
||||||
go run(op, req) // don't wait for it
|
go run(op, req) // don't wait for it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
@ -1396,8 +1396,8 @@ does it check the results.
|
|||||||
req.replyc = make(chan int)
|
req.replyc = make(chan int)
|
||||||
adder <- req
|
adder <- req
|
||||||
}
|
}
|
||||||
for i := N-1; i >= 0; i-- { // doesn't matter what order
|
for i := N - 1; i >= 0; i-- { // doesn't matter what order
|
||||||
if <-reqs[i].replyc != N + 2*i {
|
if <-reqs[i].replyc != N+2*i {
|
||||||
fmt.Println("fail at", i)
|
fmt.Println("fail at", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1425,7 +1425,7 @@ It passes the quit channel to the <code>server</code> function, which uses it li
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case req := <-service:
|
case req := <-service:
|
||||||
go run(op, req) // don't wait for it
|
go run(op, req) // don't wait for it
|
||||||
case <-quit:
|
case <-quit:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,6 @@ 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
|
key features of the language. All the programs work (at time of writing) and are
|
||||||
checked into the repository in the directory <a href='/doc/progs'>"/doc/progs/"</a>.
|
checked into the repository in the directory <a href='/doc/progs'>"/doc/progs/"</a>.
|
||||||
|
|
||||||
Program snippets are annotated with the line number in the original file; for
|
|
||||||
cleanliness, blank lines remain blank.
|
|
||||||
|
|
||||||
Hello, World
|
Hello, World
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -136,12 +133,13 @@ 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
|
After importing the "flag" package, we use a "var" declaration
|
||||||
the value of echo's "-n" flag. The variable "omitNewline" has type "*bool", pointer
|
to create and initialize a global variable, called "omitNewline",
|
||||||
to "bool".
|
to hold the value of echo's "-n" flag.
|
||||||
|
The variable has type "*bool", pointer to "bool".
|
||||||
|
|
||||||
In "main.main", we parse the arguments (line 20) and then create a local
|
In "main.main", we parse the arguments (the call to "flag.Parse") and then create a local
|
||||||
string variable we will use to build the output.
|
string variable with which to build the output.
|
||||||
|
|
||||||
The declaration statement has the form
|
The declaration statement has the form
|
||||||
|
|
||||||
@ -429,7 +427,7 @@ object. We could write
|
|||||||
return n
|
return n
|
||||||
|
|
||||||
but for simple structures like "File" it's easier to return the address of a
|
but for simple structures like "File" it's easier to return the address of a
|
||||||
composite literal, as is done here on line 21.
|
composite literal, as is done here in the "return" statement from "newFile".
|
||||||
|
|
||||||
We can use the factory to construct some familiar, exported variables of type "*File":
|
We can use the factory to construct some familiar, exported variables of type "*File":
|
||||||
|
|
||||||
@ -447,9 +445,9 @@ multi-value return as a parenthesized list of declarations; syntactically
|
|||||||
they look just like a second parameter list. The function
|
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 the first line; it declares "r" and "e" to hold the two values,
|
||||||
both of type "int" (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, "OpenFile" 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".
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user