Commit 4659685b authored by Rob Pike's avatar Rob Pike

Packages.

DELTA=170  (73 added, 21 deleted, 76 changed)
OCL=25556
CL=25594
parent e9b40580
......@@ -1101,9 +1101,9 @@ to receive. This constraint is called a channel's <i>direction</i>; either
</p>
<pre>
chan T // can send and receive values of type T
chan T // can be used to send and receive values of type T
chan &lt;- float // can only be used to send floats
&lt;-chan int // can only receive ints
&lt;-chan int // can only be used to receive ints
</pre>
<p>
......@@ -3065,27 +3065,6 @@ if x := f(); x < y {
</pre>
<!--
TODO: gri thinks that Statement needs to be changed as follows:
IfStat =
"if" [ [ SimpleStat ] ";" ] [ Expression ] Block
[ "else" ( IfStat | Block ) ] .
To facilitate the "if else if" code pattern, if the "else" branch is
simply another "if" statement, that "if" statement may be written
without the surrounding Block:
if x > 0 {
return 0;
} else if x > 10 {
return 1;
} else {
return 2;
}
-->
<h3>Switch statements</h3>
<p>
......@@ -3757,81 +3736,154 @@ m := make(map[string] int, 100); # map with initial space for 100 elements
<h2>Packages</h2>
A package is a package clause, optionally followed by import declarations,
followed by a series of declarations.
<p>
Go programs are constructed by linking together <i>packages</i>.
A package is in turn constructed from one or more source files that
together provide an interface to a set of types, constants, functions,
and variables. Those elements may be <i>imported</i> and used in
another package.
</p>
<h3>Source file organization</h3>
<p>
Each source file consists of a package clause defining the package
to which it belongs, followed by a possibly empty set of import
declarations that declare packages whose contents it wishes to use,
followed by a possibly empty set of declarations of functions,
types, variables, and constants. The source text following the
package clause acts as a block for scoping ($Declarations and scope
rules).
</p>
<pre class="grammar">
Package = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .
SourceFile = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .
</pre>
The source text following the package clause acts like a block for scoping
purposes ($Declarations and scope rules).
<h3>Package clause</h3>
<p>
Every source file identifies the package to which it belongs.
The file must begin with a package clause.
A package clause begins each source file and defines the package
to which the file belongs.
</p>
<pre class="grammar">
PackageClause = "package" PackageName .
PackageClause = "package" PackageName .
</pre>
package Math
<pre>
package math
</pre>
<p>
A set of files sharing the same PackageName form the implementation of a package.
An implementation may require that all source files for a package inhabit the same directory.
</p>
A package can gain access to exported identifiers from another package
through an import declaration:
<h3>Import</h3>
<p>
A source file gains access to exported identifiers (§Exported
identifiers) from another package through an import declaration.
In the general form, an import declaration provides an identifier
that code in the source file may use to access the imported package's
contents and a file name referring to the (compiled) implementation of
the package. The file name may be relative to a repository of
installed packages.
</p>
<pre class="grammar">
ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .
ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .
ImportSpec = [ "." | PackageName ] PackageFileName .
PackageFileName = StringLit .
ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .
ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .
ImportSpec = [ "." | PackageName ] PackageFileName .
PackageFileName = StringLit .
</pre>
An import statement makes the exported package-level identifiers of the named
package file accessible to this package.
<p>
In the following discussion, assume we have a package in the
file "/lib/math", called package "math", which exports the identifiers
"Sin" and "Cos" denoting the respective trigonometric functions.
After an import, in the usual case an exported name <i>N</i> from the imported
package <i>P</i> may be accessed by the qualified identifier
<i>P</i><code>.</code><i>N</i> (§Qualified identifiers). The actual
name <i>P</i> depends on the form of the import declaration. If
an explicit package name <code>p1</code> is provided, the qualified
identifer will have the form <code>p1.</code><i>N</i>. If no name
is provided in the import declaration, <i>P</i> will be the package
name declared within the source files of the imported package.
Finally, if the import declaration uses an explicit period
(<code>.</code>) for the package name, <i>N</i> will appear
in the package-level scope of the current file and the qualified name is
unnecessary and erroneous. In this form, it is an error if the import introduces
a name conflict.
</p>
<p>
In the general form, with an explicit package name, the import
statement declares that package name as an identifier whose
contents are the exported elements of the imported package.
For instance, after
In this table, assume we have compiled a package named
<code>math</code>, which exports function <code>Sin</code>, and
installed the compiled package in file
<code>"lib/math"</code>.
</p>
<pre>
import M "/lib/math"
<pre class="grammar">
Import syntax Local name of Sin
import M "lib/math" M.Sin
import "lib/math" math.Sin
import . "lib/math" Sin
</pre>
the contents of the package /lib/math can be accessed by
"M.Sin", "M.Cos", etc.
<h3>Multi-file packages</h3>
<p>
In its simplest form, with no package name, the import statement
implicitly uses the imported package name itself as the local
package name. After
If a package is constructed from multiple source files, all names
at package-level scope, not just exported names, are visible to all the
files in the package. An import declaration is still necessary to
declare intention to use the names,
but the imported names do not need a qualified identifer to be
accessed.
</p>
<p>
The compilation of a multi-file package may require
that the files be compiled and installed in an order that satisfies
the resolution of names imported within the package.
</p>
<p>
If source file <code>math1.go</code> contains
</p>
<pre>
import "/lib/math"
package math
const twoPi = 6.283185307179586
function Sin(x float) float { return ... }
</pre>
the contents are accessible by "math.Sin", "math.Cos".
<p>
Finally, if instead of a package name the import statement uses
an explicit period, the contents of the imported package are added
to the current package. After
and file <code>"math2.go"</code> begins
</p>
<pre>
import . "/lib/math"
package math
import "lib/math"
</pre>
the contents are accessible by "Sin" and "Cos". In this instance, it is
an error if the import introduces name conflicts.
<p>
Here is a complete example Go package that implements a concurrent prime sieve:
then, provided <code>"math1.go"</code> is compiled first and
installed in <code>"lib/math"</code>, <code>math2.go</code>
may refer directly to <code>Sin</code> and <code>twoPi</code>
without a qualified identifier.
</p>
<h3>An example package</h3>
<p>
Here is a complete Go package that implements a concurrent prime sieve.
</p>
<pre>
package main
import "fmt"
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func generate(ch chan <- int) {
for i := 2; ; i++ {
......@@ -3856,7 +3908,7 @@ func sieve() {
go generate(ch); // Start generate() as a subprocess.
for {
prime := <-ch;
print(prime, "\n");
fmt.Print(prime, "\n");
ch1 := make(chan int);
go filter(ch, ch1, prime);
ch = ch1
......@@ -3972,7 +4024,7 @@ Program execution begins by initializing the <code>main</code> package and then
invoking <code>main.main()</code>.
</p>
<p>
When main.main() returns, the program exits.
When <code>main.main()</code> returns, the program exits.
</p>
<hr/>
......
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