diff options
author | Rob Pike <r@golang.org> | 2008-09-12 16:03:16 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2008-09-12 16:03:16 -0700 |
commit | daf0485787cc8e926a57a75cbc46ca6ef80c6268 (patch) | |
tree | 1ada0da1e635b28393f7f518c69e0352ef78d2e3 | |
parent | 0264cfecfdfebe0b1f9017073a980c7628459b84 (diff) | |
download | golang-daf0485787cc8e926a57a75cbc46ca6ef80c6268.tar.gz |
next section: i/o package that has structs, methods
R=gri
DELTA=137 (134 added, 0 deleted, 3 changed)
OCL=15251
CL=15259
-rw-r--r-- | doc/go_tutorial.txt | 73 | ||||
-rw-r--r-- | doc/progs/fd.go | 58 | ||||
-rw-r--r-- | doc/progs/helloworld3.go | 17 |
3 files changed, 145 insertions, 3 deletions
diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt index e1c5456bd..48f25a273 100644 --- a/doc/go_tutorial.txt +++ b/doc/go_tutorial.txt @@ -1,4 +1,4 @@ -Get Going +Let's Go ---- Rob Pike @@ -9,7 +9,8 @@ Rob Pike This document is a tutorial introduction to the basics of the Go systems programming language, intended for programmers familiar with C or C++. It is not a comprehensive -guide to the language; at the moment the closest to that is the draft specification: +guide to the language; at the moment the document closest to that is the draft +specification: /doc/go_lang.html @@ -79,7 +80,7 @@ top-level declaration, even though they are needed as separators <i>within</i> a parenthesized list of declarations. Having imported the "Flag" package, line 8 creates a global variable to hold -the value of echo's -n flag. (The nil indicates a nice feature not needed here; +the value of echo's -n flag. (The nil hides a nice feature not needed here; see the source in "src/lib/flag.go" for details). In "main.main", we parse the arguments (line 16) and then create a local @@ -233,3 +234,69 @@ sign or size to another, and between ints and floats, plus a few other simple cases. There are no automatic conversions of any kind in Go, other than that of making constants have concrete size and type when assigned to a variable. + +An I/O Package +---- + +Next we'll look at a simple package for doing file I/O with the usual +sort of open/close/read/write interface. Here's the start of "fd.go": + +--PROG progs/fd.go /package/ /^}/ + +The first line declares the name of the package -- "fd" for ''file descriptor'' -- +and then we import the low-level, external "syscall" package, which provides +a primitive interface to the underlying operating system's calls. + +Next is a type definition: the "type" keyword introduces a type declaration, +in this case a data structure called "FD". +To make things a little more interesting, our "FD" includes the name of the file +that the file descriptor refers to. The "export" keyword makes the declared +structure visible to users of the package. + +Now we can write what is often called a factory: + +--PROG progs/fd.go /NewFD/ /^}/ + +This returns a pointer to a new "FD" structure with the file descriptor and name +filled in. We can use it to construct some familiar, exported variables of type "*FD": + +--PROG progs/fd.go /export.var/ /^.$/ + +The "NewFD" function was not exported because it's internal. The proper factory +to use is "Open": + +--PROG progs/fd.go /func.Open/ /^}/ + +There are a number of new things in these few lines. First, "Open" returns +multiple values, an "FD" and an "errno" (Unix error number). We declare the +multi-value return as a parenthesized list of declarations. "Syscall.open" +also has a multi-value return, which we can grab with the multi-variable +declaration on line 27; it declares "r" and "e" to hold the two values, +both of type "int64" (although you'd have to look at the "syscall" package +to see that). Finally, line 28 returns two values: a pointer to the new "FD" +and the return code. If "Syscall.open" failed, the file descriptor "r" will +be negative and "NewFD" will return "nil". + +Now that we can build "FDs", we can write methods to use them. To declare +a method of a type, we define a function to have an explicit receiver +of that type, placed +in parentheses before the function name. Here are some methods for "FD", +each of which declares a receiver variable "fd". + +--PROG progs/fd.go /Close/ END + +There is no implicit "this" and the receiver variable must be used to access +members of the structure. Methods are not declared within +the "struct" declaration itself. The "struct" declaration defines only data members. + +Finally, we can use our new package: + +--PROG progs/helloworld3.go + +and run the program: + + % helloworld3 + hello, world + can't open file; errno=2 + % + diff --git a/doc/progs/fd.go b/doc/progs/fd.go new file mode 100644 index 000000000..50d33624a --- /dev/null +++ b/doc/progs/fd.go @@ -0,0 +1,58 @@ +// 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 fd + +import Syscall "syscall" + +export type FD struct { + fildes int64; // file descriptor number + name string; // file name at Open time +} + +func NewFD(fd int64, name string) *FD { + if fd < 0 { + return nil + } + n := new(FD); + n.fildes = fd; + n.name = name; + return n +} + +export var ( + Stdin = NewFD(0, "/dev/stdin"); + Stdout = NewFD(1, "/dev/stdout"); + Stderr = NewFD(2, "/dev/stderr"); +) + +export func Open(name string, mode int64, perm int64) (fd *FD, errno int64) { + r, e := Syscall.open(name, mode, perm); + return NewFD(r, name), e +} + +func (fd *FD) Close() int64 { + if fd == nil { + return Syscall.EINVAL + } + r, e := Syscall.close(fd.fildes); + fd.fildes = -1; // so it can't be closed again + return 0 +} + +func (fd *FD) Read(b *[]byte) (ret int64, errno int64) { + if fd == nil { + return -1, Syscall.EINVAL + } + r, e := Syscall.read(fd.fildes, &b[0], int64(len(b))); + return r, e +} + +func (fd *FD) Write(b *[]byte) (ret int64, errno int64) { + if fd == nil { + return -1, Syscall.EINVAL + } + r, e := Syscall.write(fd.fildes, &b[0], int64(len(b))); + return r, e +} diff --git a/doc/progs/helloworld3.go b/doc/progs/helloworld3.go new file mode 100644 index 000000000..540036865 --- /dev/null +++ b/doc/progs/helloworld3.go @@ -0,0 +1,17 @@ +// 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 FD "fd" + +func main() { + hello := []byte{'h', 'e', 'l', 'l', 'o', ', ', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}; + FD.Stdout.Write(&hello); + fd, errno := FD.Open("/does/not/exist", 0, 0); + if fd == nil { + print("can't open file; errno=", errno, "\n"); + sys.exit(1); + } +} |