Commit 40d54352 authored by Rob Pike's avatar Rob Pike

update tutorial to new language.

add a section on printing
add a section on allocation

R=rsc
DELTA=500  (278 added, 15 deleted, 207 changed)
OCL=22381
CL=22456
parent dfc3e523
This diff is collapsed.
...@@ -20,6 +20,11 @@ ...@@ -20,6 +20,11 @@
# #
# non-blank lines are annotated with line number in file # non-blank lines are annotated with line number in file
# line numbers are printed %.2d to make them equal-width for nice formatting.
# the format gives a leading 0. the format %2d gives a leading space but
# that appears to confuse sanjay's makehtml formatter into bungling quotes
# because it makes some lines look indented.
echo "<pre> <!-- $* -->" echo "<pre> <!-- $* -->"
case $# in case $# in
...@@ -27,27 +32,31 @@ case $# in ...@@ -27,27 +32,31 @@ case $# in
if test "$3" = "END" # $2 to end of file if test "$3" = "END" # $2 to end of file
then then
awk ' awk '
function LINE() { printf("%.2d\t%s\n", NR, $0) }
BEGIN { printing = 0 } BEGIN { printing = 0 }
'$2' { printing = 1; print NR "\t" $0; getline } '$2' { printing = 1; LINE(); getline }
printing { if($0 ~ /./) { print NR "\t" $0 } else { print "" } } printing { if($0 ~ /./) { LINE() } else { print "" } }
' '
else # $2 through $3 else # $2 through $3
awk ' awk '
function LINE() { printf("%.2d\t%s\n", NR, $0) }
BEGIN { printing = 0 } BEGIN { printing = 0 }
'$2' { printing = 1; print NR "\t" $0; getline } '$2' { printing = 1; LINE(); getline }
'$3' && printing { if(printing) {printing = 0; print NR "\t" $0; exit} } '$3' && printing { if(printing) {printing = 0; LINE(); exit} }
printing { if($0 ~ /./) { print NR "\t" $0 } else { print "" } } printing { if($0 ~ /./) { LINE() } else { print "" } }
' '
fi fi
;; ;;
2) # one line 2) # one line
awk ' awk '
'$2' { print NR "\t" $0; getline; exit } function LINE() { printf("%.2d\t%s\n", NR, $0) }
'$2' { LINE(); getline; exit }
' '
;; ;;
1) # whole file 1) # whole file
awk ' awk '
{ if($0 ~ /./) { print NR "\t" $0 } else { print "" } } function LINE() { printf("%.2d\t%s\n", NR, $0) }
{ if($0 ~ /./) { LINE() } else { print "" } }
' '
;; ;;
*) *)
......
...@@ -5,40 +5,40 @@ ...@@ -5,40 +5,40 @@
package main package main
import ( import (
FD "fd"; "fd";
Flag "flag"; "flag";
) )
func cat(fd *FD.FD) { func cat(file *fd.FD) {
const NBUF = 512; const NBUF = 512;
var buf [NBUF]byte; var buf [NBUF]byte;
for { for {
switch nr, er := fd.Read(buf); true { switch nr, er := file.Read(buf); true {
case nr < 0: case nr < 0:
print("error reading from ", fd.Name(), ": ", er, "\n"); print("error reading from ", file.String(), ": ", er.String(), "\n");
sys.exit(1); sys.exit(1);
case nr == 0: // EOF case nr == 0: // EOF
return; return;
case nr > 0: case nr > 0:
if nw, ew := FD.Stdout.Write(buf[0:nr]); nw != nr { if nw, ew := fd.Stdout.Write(buf[0:nr]); nw != nr {
print("error writing from ", fd.Name(), ": ", ew, "\n"); print("error writing from ", file.String(), ": ", ew.String(), "\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
if Flag.NArg() == 0 { if flag.NArg() == 0 {
cat(FD.Stdin); cat(fd.Stdin);
} }
for i := 0; i < Flag.NArg(); i++ { for i := 0; i < flag.NArg(); i++ {
fd, err := FD.Open(Flag.Arg(i), 0, 0); file, err := fd.Open(flag.Arg(i), 0, 0);
if fd == nil { if file == nil {
print("can't open ", Flag.Arg(i), ": error ", err, "\n"); print("can't open ", flag.Arg(i), ": error ", err, "\n");
sys.exit(1); sys.exit(1);
} }
cat(fd); cat(file);
fd.Close(); file.Close();
} }
} }
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
package main package main
import ( import (
FD "fd"; "fd";
Flag "flag"; "flag";
"os";
) )
var rot13_flag = Flag.Bool("rot13", false, nil, "rot13 the input") var rot13_flag = 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' {
...@@ -22,8 +23,8 @@ func rot13(b byte) byte { ...@@ -22,8 +23,8 @@ func rot13(b byte) byte {
} }
type Reader interface { type Reader interface {
Read(b []byte) (ret int64, errno int64); Read(b []byte) (ret int, err *os.Error);
Name() string; String() string;
} }
type Rot13 struct { type Rot13 struct {
...@@ -31,21 +32,19 @@ type Rot13 struct { ...@@ -31,21 +32,19 @@ type Rot13 struct {
} }
func NewRot13(source Reader) *Rot13 { func NewRot13(source Reader) *Rot13 {
r13 := new(Rot13); return &Rot13{source}
r13.source = source;
return r13
} }
func (r13 *Rot13) Read(b []byte) (ret int64, errno int64) { // TODO: use standard Read sig? func (r13 *Rot13) Read(b []byte) (ret int, err *os.Error) {
r, e := r13.source.Read(b); r, e := r13.source.Read(b);
for i := int64(0); i < r; i++ { for i := 0; i < r; i++ {
b[i] = rot13(b[i]) b[i] = rot13(b[i])
} }
return r, e return r, e
} }
func (r13 *Rot13) Name() string { func (r13 *Rot13) String() string {
return r13.source.Name() return r13.source.String()
} }
// end of Rot13 implementation // end of Rot13 implementation
...@@ -53,38 +52,37 @@ func cat(r Reader) { ...@@ -53,38 +52,37 @@ func cat(r Reader) {
const NBUF = 512; const NBUF = 512;
var buf [NBUF]byte; var buf [NBUF]byte;
if rot13_flag.BVal() { if *rot13_flag {
r = NewRot13(r) r = NewRot13(r)
} }
for { for {
switch nr, er := r.Read(buf); { switch nr, er := r.Read(buf); {
case nr < 0: case nr < 0:
print("error reading from ", r.Name(), ": ", er, "\n"); print("error reading from ", r.String(), ": ", er.String(), "\n");
sys.exit(1); sys.exit(1);
case nr == 0: // EOF case nr == 0: // EOF
return; return;
case nr > 0: case nr > 0:
nw, ew := FD.Stdout.Write(buf[0:nr]); nw, ew := fd.Stdout.Write(buf[0:nr]);
if nw != nr { if nw != nr {
print("error writing from ", r.Name(), ": ", ew, "\n"); print("error writing from ", r.String(), ": ", ew.String(), "\n");
} }
} }
} }
} }
func main() { func main() {
var bug FD.FD; flag.Parse(); // Scans the arg list and sets up flags
Flag.Parse(); // Scans the arg list and sets up flags if flag.NArg() == 0 {
if Flag.NArg() == 0 { cat(fd.Stdin);
cat(FD.Stdin);
} }
for i := 0; i < Flag.NArg(); i++ { for i := 0; i < flag.NArg(); i++ {
fd, err := FD.Open(Flag.Arg(i), 0, 0); file, err := fd.Open(flag.Arg(i), 0, 0);
if fd == nil { if file == nil {
print("can't open ", Flag.Arg(i), ": error ", err, "\n"); print("can't open ", flag.Arg(i), ": error ", err, "\n");
sys.exit(1); sys.exit(1);
} }
cat(fd); cat(file);
fd.Close(); file.Close();
} }
} }
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
package main package main
import ( import (
OS "os"; "os";
Flag "flag"; "flag";
) )
var n_flag = Flag.Bool("n", false, nil, "don't print final newline") var n_flag = flag.Bool("n", false, "don't print final newline")
const ( const (
Space = " "; Space = " ";
...@@ -17,16 +17,16 @@ const ( ...@@ -17,16 +17,16 @@ const (
) )
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 {
s += Space s += Space
} }
s += Flag.Arg(i) s += flag.Arg(i)
} }
if !n_flag.BVal() { if !*n_flag {
s += Newline s += Newline
} }
OS.Stdout.WriteString(s); os.Stdout.WriteString(s);
} }
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
package fd package fd
import Syscall "syscall" import (
"os";
"syscall";
)
export type FD struct { export type FD struct {
fildes int64; // file descriptor number fildes int64; // file descriptor number
...@@ -15,10 +18,7 @@ func NewFD(fd int64, name string) *FD { ...@@ -15,10 +18,7 @@ func NewFD(fd int64, name string) *FD {
if fd < 0 { if fd < 0 {
return nil return nil
} }
n := new(FD); return &FD{fd, name}
n.fildes = fd;
n.name = name;
return n
} }
export var ( export var (
...@@ -27,36 +27,36 @@ export var ( ...@@ -27,36 +27,36 @@ export var (
Stderr = NewFD(2, "/dev/stderr"); Stderr = NewFD(2, "/dev/stderr");
) )
export func Open(name string, mode int64, perm int64) (fd *FD, errno int64) { export func Open(name string, mode int64, perm int64) (fd *FD, err *os.Error) {
r, e := Syscall.open(name, mode, perm); r, e := syscall.open(name, mode, perm);
return NewFD(r, name), e return NewFD(r, name), os.ErrnoToError(e)
} }
func (fd *FD) Close() int64 { func (fd *FD) Close() *os.Error {
if fd == nil { if fd == nil {
return Syscall.EINVAL return os.EINVAL
} }
r, e := Syscall.close(fd.fildes); r, e := syscall.close(fd.fildes);
fd.fildes = -1; // so it can't be closed again fd.fildes = -1; // so it can't be closed again
return 0 return nil
} }
func (fd *FD) Read(b []byte) (ret int64, errno int64) { func (fd *FD) Read(b []byte) (ret int, err *os.Error) {
if fd == nil { if fd == nil {
return -1, Syscall.EINVAL return -1, os.EINVAL
} }
r, e := Syscall.read(fd.fildes, &b[0], int64(len(b))); r, e := syscall.read(fd.fildes, &b[0], int64(len(b)));
return r, e return int(r), os.ErrnoToError(e)
} }
func (fd *FD) Write(b []byte) (ret int64, errno int64) { func (fd *FD) Write(b []byte) (ret int, err *os.Error) {
if fd == nil { if fd == nil {
return -1, Syscall.EINVAL return -1, os.EINVAL
} }
r, e := Syscall.write(fd.fildes, &b[0], int64(len(b))); r, e := syscall.write(fd.fildes, &b[0], int64(len(b)));
return r, e return int(r), os.ErrnoToError(e)
} }
func (fd *FD) Name() string { func (fd *FD) String() string {
return fd.name return fd.name
} }
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
package main package main
import OS "os" // this package contains features for basic I/O import "os" // this package contains features for basic I/O
func main() { func main() {
OS.Stdout.WriteString("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n"); os.Stdout.WriteString("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
} }
...@@ -4,14 +4,14 @@ ...@@ -4,14 +4,14 @@
package main package main
import FD "fd" import fd "fd"
func main() { func main() {
hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}; hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'};
FD.Stdout.Write(hello); fd.Stdout.Write(hello);
fd, errno := FD.Open("/does/not/exist", 0, 0); file, err := fd.Open("/does/not/exist", 0, 0);
if fd == nil { if file == nil {
print("can't open file; errno=", errno, "\n"); print("can't open file; err=", err.String(), "\n");
sys.exit(1); sys.exit(1);
} }
} }
// 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() {
var u64 uint64 = 1<<64-1;
fmt.printf("%d %d\n", u64, int64(u64));
// harder stuff
type T struct { a int; b string };
t := T{77, "Sunset Strip"};
a := []int{1, 2, 3, 4};
fmt.printf("%v %v %v\n", u64, t, a);
fmt.print(u64, " ", t, " ", a, "\n");
fmt.println(u64, t, a);
}
// 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"
type T struct { a int; b string }
func (t *T) String() string {
return fmt.sprint(t.a) + " " + t.b
}
func main() {
t := &T{77, "Sunset Strip"};
fmt.println(t)
}
// 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");
}
...@@ -16,6 +16,9 @@ for i in \ ...@@ -16,6 +16,9 @@ for i in \
sum.go \ sum.go \
sort.go \ sort.go \
sortmain.go \ sortmain.go \
print.go \
printf.go \
print_string.go \
sieve.go \ sieve.go \
sieve1.go \ sieve1.go \
server1.go \ server1.go \
...@@ -46,7 +49,7 @@ function testitpipe { ...@@ -46,7 +49,7 @@ function testitpipe {
testit helloworld "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界" testit helloworld "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
testit helloworld2 "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界" testit helloworld2 "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
testit helloworld3 "" "hello, world can't open file; errno=2" testit helloworld3 "" "hello, world can't open file; err=No such file or directory"
testit echo "hello, world" "hello, world" testit echo "hello, world" "hello, world"
testit sum "" "6" testit sum "" "6"
...@@ -58,6 +61,10 @@ echo $rot13 | testit cat_rot13 "--rot13" $alphabet ...@@ -58,6 +61,10 @@ echo $rot13 | testit cat_rot13 "--rot13" $alphabet
testit sortmain "" "Sunday Monday Tuesday Thursday Friday" 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" testitpipe sieve "sed 10q" "2 3 5 7 11 13 17 19 23 29"
testitpipe sieve "sed 10q" "2 3 5 7 11 13 17 19 23 29" testitpipe sieve "sed 10q" "2 3 5 7 11 13 17 19 23 29"
......
...@@ -5,26 +5,23 @@ ...@@ -5,26 +5,23 @@
package sort package sort
export type SortInterface interface { export type SortInterface interface {
len() int; Len() int;
less(i, j int) bool; Less(i, j int) bool;
swap(i, j int); Swap(i, j int);
} }
export func Sort(data SortInterface) { export func Sort(data SortInterface) {
// Bubble sort for brevity for i := 1; i < data.Len(); i++ {
for i := 0; i < data.len(); i++ { for j := i; j > 0 && data.Less(j, j-1); j-- {
for j := i; j < data.len(); j++ { data.Swap(j, j-1);
if data.less(j, i) {
data.swap(i, j)
}
} }
} }
} }
export func IsSorted(data SortInterface) bool { export func IsSorted(data SortInterface) bool {
n := data.len(); n := data.Len();
for i := n - 1; i > 0; i-- { for i := n - 1; i > 0; i-- {
if data.less(i, i - 1) { if data.Less(i, i - 1) {
return false; return false;
} }
} }
...@@ -33,40 +30,34 @@ export func IsSorted(data SortInterface) bool { ...@@ -33,40 +30,34 @@ export func IsSorted(data SortInterface) bool {
// Convenience types for common cases // Convenience types for common cases
export type IntArray struct { export type IntArray []int
data *[]int;
}
func (p *IntArray) len() int { return len(p.data); } func (p IntArray) Len() int { return len(p); }
func (p *IntArray) less(i, j int) bool { return p.data[i] < p.data[j]; } func (p IntArray) Less(i, j int) bool { return p[i] < p[j]; }
func (p *IntArray) swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i]; } func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
export type FloatArray struct { export type FloatArray []float
data *[]float;
}
func (p *FloatArray) len() int { return len(p.data); } func (p FloatArray) Len() int { return len(p); }
func (p *FloatArray) less(i, j int) bool { return p.data[i] < p.data[j]; } func (p FloatArray) Less(i, j int) bool { return p[i] < p[j]; }
func (p *FloatArray) swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i]; } func (p FloatArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
export type StringArray struct { export type StringArray []string
data *[]string;
}
func (p *StringArray) len() int { return len(p.data); } func (p StringArray) Len() int { return len(p); }
func (p *StringArray) less(i, j int) bool { return p.data[i] < p.data[j]; } func (p StringArray) Less(i, j int) bool { return p[i] < p[j]; }
func (p *StringArray) swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i]; } func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
// Convenience wrappers for common cases // Convenience wrappers for common cases
export func SortInts(a *[]int) { Sort(&IntArray{a}); } export func SortInts(a []int) { Sort(IntArray(a)); }
export func SortFloats(a *[]float) { Sort(&FloatArray{a}); } export func SortFloats(a []float) { Sort(FloatArray(a)); }
export func SortStrings(a *[]string) { Sort(&StringArray{a}); } export func SortStrings(a []string) { Sort(StringArray(a)); }
export func IntsAreSorted(a *[]int) bool { return IsSorted(&IntArray{a}); } export func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)); }
export func FloatsAreSorted(a *[]float) bool { return IsSorted(&FloatArray{a}); } export func FloatsAreSorted(a []float) bool { return IsSorted(FloatArray(a)); }
export func StringsAreSorted(a *[]string) bool { return IsSorted(&StringArray{a}); } export func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)); }
...@@ -4,22 +4,22 @@ ...@@ -4,22 +4,22 @@
package main package main
import Sort "sort" import "sort"
func ints() { func ints() {
data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}; data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586};
a := Sort.IntArray{&data}; a := sort.IntArray(data);
Sort.Sort(&a); sort.Sort(a);
if !Sort.IsSorted(&a) { if !sort.IsSorted(a) {
panic() panic()
} }
} }
func strings() { func strings() {
data := []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}; data := []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"};
a := Sort.StringArray{&data}; a := sort.StringArray(data);
Sort.Sort(&a); sort.Sort(a);
if !Sort.IsSorted(&a) { if !sort.IsSorted(a) {
panic() panic()
} }
} }
...@@ -31,12 +31,12 @@ type Day struct { ...@@ -31,12 +31,12 @@ type Day struct {
} }
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]; }
func days() { func days() {
Sunday := Day{ 0, "SUN", "Sunday" }; Sunday := Day{ 0, "SUN", "Sunday" };
...@@ -47,13 +47,13 @@ func days() { ...@@ -47,13 +47,13 @@ func days() {
Friday := Day{ 5, "FRI", "Friday" }; Friday := Day{ 5, "FRI", "Friday" };
Saturday := Day{ 6, "SAT", "Saturday" }; Saturday := Day{ 6, "SAT", "Saturday" };
data := []*Day{&Tuesday, &Thursday, &Sunday, &Monday, &Friday}; data := []*Day{&Tuesday, &Thursday, &Sunday, &Monday, &Friday};
a := DayArray{&data}; a := DayArray{data};
Sort.Sort(&a); sort.Sort(&a);
if !Sort.IsSorted(&a) { if !sort.IsSorted(&a) {
panic() panic()
} }
for i := 0; i < len(data); i++ { for i, d := range data {
print(data[i].long_name, " ") print(d.long_name, " ")
} }
print("\n") print("\n")
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
package main package main
func sum(a *[]int) int { // returns an int func sum(a []int) int { // returns an int
s := 0; s := 0;
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
s += a[i] s += a[i]
...@@ -14,6 +14,6 @@ func sum(a *[]int) int { // returns an int ...@@ -14,6 +14,6 @@ func sum(a *[]int) int { // returns an int
func main() { func main() {
s := sum(&[]int{1,2,3}); // pass address of int array s := sum([3]int{1,2,3}); // a slice of the array is passed to sum
print(s, "\n"); print(s, "\n");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment