2008-03-04 23:18:16 -07:00
|
|
|
The Go Programming Language
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-04-29 17:27:11 -06:00
|
|
|
(April 29, 2008)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
This document is an informal specification/proposal for a new systems programming
|
|
|
|
language.
|
|
|
|
|
|
|
|
|
|
|
|
Guiding principles
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Go is a new systems programming language intended as an alternative to C++ at
|
|
|
|
Google. Its main purpose is to provide a productive and efficient programming
|
|
|
|
environment for compiled programs such as servers and distributed systems.
|
|
|
|
|
|
|
|
The design is motivated by the following guidelines:
|
|
|
|
|
|
|
|
- very fast compilation (1MLOC/s stretch goal); instantaneous incremental compilation
|
|
|
|
- procedural
|
|
|
|
- strongly typed
|
|
|
|
- concise syntax avoiding repetition
|
|
|
|
- few, orthogonal, and general concepts
|
2008-03-06 00:00:44 -07:00
|
|
|
- support for threading and interprocess communication
|
|
|
|
- garbage collection
|
2008-03-04 23:18:16 -07:00
|
|
|
- container library written in Go
|
|
|
|
- reasonably efficient (C ballpark)
|
|
|
|
|
|
|
|
The language should be strong enough that the compiler and run time can be
|
|
|
|
written in itself.
|
|
|
|
|
|
|
|
|
|
|
|
Modularity, identifiers and scopes
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A Go program consists of one or more `packages' compiled separately, though
|
|
|
|
not independently. A single package may make
|
|
|
|
individual identifiers visible to other files by marking them as
|
2008-03-06 20:40:52 -07:00
|
|
|
exported; there is no ``header file''.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A package collects types, constants, functions, and so on into a named
|
2008-03-06 00:00:44 -07:00
|
|
|
entity that may be exported to enable its constituents be used in
|
2008-03-04 23:18:16 -07:00
|
|
|
another compilation unit.
|
|
|
|
|
|
|
|
Because there are no header files, all identifiers in a package are either
|
2008-03-06 00:00:44 -07:00
|
|
|
declared explicitly within the package or arise from an import statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Scoping is essentially the same as in C.
|
|
|
|
|
|
|
|
|
|
|
|
Program structure
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A compilation unit (usually a single source file)
|
|
|
|
consists of a package specifier followed by import
|
|
|
|
declarations followed by other declarations. There are no statements
|
|
|
|
at the top level of a file.
|
|
|
|
|
|
|
|
A program consists of a number of packages. By convention, one
|
2008-03-17 20:05:07 -06:00
|
|
|
package, by default called main, is the starting point for execution.
|
|
|
|
It contains a function, also called main, that is the first function invoked
|
2008-03-04 23:18:16 -07:00
|
|
|
by the run time system.
|
|
|
|
|
|
|
|
If any package within the program
|
2008-03-17 20:05:07 -06:00
|
|
|
contains a function init(), that function will be executed
|
|
|
|
before main.main() is called. The details of initialization are
|
2008-03-04 23:18:16 -07:00
|
|
|
still under development.
|
|
|
|
|
|
|
|
|
|
|
|
Typing, polymorphism, and object-orientation
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
Go programs are strongly typed. Certain values can also be
|
|
|
|
polymorphic. The language provides mechanisms to make use of such
|
|
|
|
polymorphic values type-safe.
|
2008-03-26 00:53:07 -06:00
|
|
|
|
|
|
|
Interface types, building on structures with methods, provide
|
|
|
|
the mechanisms to support object-oriented programming.
|
|
|
|
Different interface types are independent of each
|
2008-03-04 23:18:16 -07:00
|
|
|
other and no explicit hierarchy is required (such as single or
|
|
|
|
multiple inheritance explicitly specified through respective type
|
|
|
|
declarations). Interface types only define a set of methods that a
|
|
|
|
corresponding implementation must provide. Thus interface and
|
|
|
|
implementation are strictly separated.
|
|
|
|
|
|
|
|
An interface is implemented by associating methods with
|
|
|
|
structures. If a structure implements all methods of an interface, it
|
|
|
|
implements that interface and thus can be used where that interface is
|
|
|
|
required. Unless used through a variable of interface type, methods
|
2008-03-06 20:40:52 -07:00
|
|
|
can always be statically bound (they are not ``virtual''), and incur no
|
2008-03-04 23:18:16 -07:00
|
|
|
runtime overhead compared to an ordinary function.
|
|
|
|
|
|
|
|
Go has no explicit notion of classes, sub-classes, or inheritance.
|
|
|
|
These concepts are trivially modeled in Go through the use of
|
|
|
|
functions, structures, associated methods, and interfaces.
|
|
|
|
|
|
|
|
Go has no explicit notion of type parameters or templates. Instead,
|
|
|
|
containers (such as stacks, lists, etc.) are implemented through the
|
2008-03-27 18:19:17 -06:00
|
|
|
use of abstract operations on interface types or polymorphic values.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Pointers and garbage collection
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Variables may be allocated automatically (when entering the scope of
|
|
|
|
the variable) or explicitly on the heap. Pointers are used to refer
|
|
|
|
to heap-allocated variables. Pointers may also be used to point to
|
|
|
|
any other variable; such a pointer is obtained by "taking the
|
|
|
|
address" of that variable. Variables are automatically reclaimed when
|
|
|
|
they are no longer accessible. There is no pointer arithmetic in Go.
|
|
|
|
|
|
|
|
|
|
|
|
Functions
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Functions contain declarations and statements. They may be
|
|
|
|
recursive. Functions may be anonymous and appear as
|
|
|
|
literals in expressions.
|
|
|
|
|
|
|
|
|
|
|
|
Multithreading and channels
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Go supports multithreaded programming directly. A function may
|
|
|
|
be invoked as a parallel thread of execution. Communication and
|
|
|
|
synchronization is provided through channels and their associated
|
|
|
|
language support.
|
|
|
|
|
|
|
|
|
|
|
|
Values and references
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
All objects have value semantics, but their contents may be accessed
|
2008-03-06 00:00:44 -07:00
|
|
|
through different pointers referring to the same object.
|
2008-03-04 23:18:16 -07:00
|
|
|
For example, when calling a function with an array, the array is
|
|
|
|
passed by value, possibly by making a copy. To pass a reference,
|
|
|
|
one must explicitly pass a pointer to the array. For arrays in
|
|
|
|
particular, this is different from C.
|
|
|
|
|
|
|
|
There is also a built-in string type, which represents immutable
|
2008-03-26 00:53:07 -06:00
|
|
|
strings of bytes.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Syntax
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
The syntax of statements and expressions in Go borrows from the C tradition;
|
|
|
|
declarations are loosely derived from the Pascal tradition to allow more
|
|
|
|
comprehensible composability of types.
|
|
|
|
|
|
|
|
Here is a complete example Go program that implements a concurrent prime sieve:
|
|
|
|
|
|
|
|
|
2008-03-17 20:05:07 -06:00
|
|
|
package main
|
2008-03-06 20:40:52 -07:00
|
|
|
|
|
|
|
// Send the sequence 2, 3, 4, ... to channel 'ch'.
|
|
|
|
func Generate(ch *chan> int) {
|
|
|
|
for i := 2; ; i++ {
|
2008-03-11 19:07:22 -06:00
|
|
|
>ch = i // Send 'i' to channel 'ch'.
|
2008-03-06 20:40:52 -07:00
|
|
|
}
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
2008-03-06 20:40:52 -07:00
|
|
|
|
|
|
|
// Copy the values from channel 'in' to channel 'out',
|
|
|
|
// removing those divisible by 'prime'.
|
|
|
|
func Filter(in *chan< int, out *chan> int, prime int) {
|
2008-03-06 23:14:17 -07:00
|
|
|
for {
|
2008-03-06 20:40:52 -07:00
|
|
|
i := <in; // Receive value of new variable 'i' from 'in'.
|
|
|
|
if i % prime != 0 {
|
2008-03-11 19:07:22 -06:00
|
|
|
>out = i // Send 'i' to channel 'out'.
|
2008-03-06 20:40:52 -07:00
|
|
|
}
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
|
|
|
}
|
2008-03-06 20:40:52 -07:00
|
|
|
|
|
|
|
// The prime sieve: Daisy-chain Filter processes together.
|
|
|
|
func Sieve() {
|
|
|
|
ch := new(chan int); // Create a new channel.
|
|
|
|
go Generate(ch); // Start Generate() as a subprocess.
|
2008-03-06 23:14:17 -07:00
|
|
|
for {
|
2008-03-06 20:40:52 -07:00
|
|
|
prime := <ch;
|
|
|
|
printf("%d\n", prime);
|
|
|
|
ch1 := new(chan int);
|
|
|
|
go Filter(ch, ch1, prime);
|
2008-03-11 19:07:22 -06:00
|
|
|
ch = ch1
|
2008-03-06 20:40:52 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-17 20:05:07 -06:00
|
|
|
func main() {
|
2008-03-11 19:07:22 -06:00
|
|
|
Sieve()
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Notation
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
The syntax is specified using Extended Backus-Naur Form (EBNF).
|
|
|
|
In particular:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
- | separates alternatives (least binding strength)
|
2008-03-26 00:53:07 -06:00
|
|
|
- () groups
|
|
|
|
- [] specifies an option (0 or 1 times)
|
2008-03-06 20:40:52 -07:00
|
|
|
- {} specifies repetition (0 to n times)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
Lexical symbols are enclosed in double quotes '''' (the
|
|
|
|
double quote symbol is written as ''"'').
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
A production may be referenced from various places in this document
|
2008-03-11 17:02:46 -06:00
|
|
|
but is usually defined close to its first use. Productions and code
|
|
|
|
examples are indented.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Lower-case production names are used to identify productions that cannot
|
|
|
|
be broken by white space or comments; they are usually tokens. Other
|
|
|
|
productions are in CamelCase.
|
|
|
|
|
|
|
|
|
|
|
|
Common productions
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
IdentifierList = identifier { "," identifier } .
|
|
|
|
ExpressionList = Expression { "," Expression } .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
QualifiedIdent = [ PackageName "." ] identifier .
|
2008-03-11 15:37:16 -06:00
|
|
|
PackageName = identifier .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Source code representation
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Source code is Unicode text encoded in UTF-8.
|
|
|
|
|
|
|
|
Tokenization follows the usual rules. Source text is case-sensitive.
|
|
|
|
|
|
|
|
White space is blanks, newlines, carriage returns, or tabs.
|
|
|
|
|
|
|
|
Comments are // to end of line or /* */ without nesting and are treated as white space.
|
|
|
|
|
|
|
|
Some Unicode characters (e.g., the character U+00E4) may be representable in
|
|
|
|
two forms, as a single code point or as two code points. For simplicity of
|
|
|
|
implementation, Go treats these as distinct characters.
|
|
|
|
|
|
|
|
|
|
|
|
Characters
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
In the grammar we use the notation
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
utf8_char
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
to refer to an arbitrary Unicode code point encoded in UTF-8.
|
|
|
|
|
|
|
|
|
|
|
|
Digits and Letters
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
oct_digit = { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" } .
|
|
|
|
dec_digit = { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" } .
|
2008-03-11 17:02:46 -06:00
|
|
|
hex_digit = { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "a" |
|
|
|
|
"A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "E" | "f" | "F" } .
|
|
|
|
letter = "A" | "a" | ... "Z" | "z" | "_" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
For simplicity, letters and digits are ASCII. We may in time allow
|
|
|
|
Unicode identifiers.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Identifiers
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
An identifier is a name for a program entity such as a variable, a
|
2008-03-06 00:00:44 -07:00
|
|
|
type, a function, etc. An identifier must not be a reserved word.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
identifier = letter { letter | dec_digit } .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
a
|
|
|
|
_x
|
|
|
|
ThisIsVariable9
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
A type specifies the set of values that variables of that type may
|
2008-03-04 23:18:16 -07:00
|
|
|
assume, and the operators that are applicable.
|
|
|
|
|
|
|
|
There are basic types and compound types constructed from them.
|
|
|
|
|
|
|
|
|
|
|
|
Basic types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Go defines a number of basic types, referred to by their
|
2008-03-04 23:18:16 -07:00
|
|
|
predeclared type names. There are signed and unsigned integer
|
|
|
|
and floating point types:
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
bool the truth values true and false
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
uint8 the set of all unsigned 8-bit integers
|
|
|
|
uint16 the set of all unsigned 16-bit integers
|
|
|
|
uint32 the set of all unsigned 32-bit integers
|
|
|
|
unit64 the set of all unsigned 64-bit integers
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
byte alias for uint8
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
int8 the set of all signed 8-bit integers, in 2's complement
|
|
|
|
int16 the set of all signed 16-bit integers, in 2's complement
|
|
|
|
int32 the set of all signed 32-bit integers, in 2's complement
|
|
|
|
int64 the set of all signed 64-bit integers, in 2's complement
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
float32 the set of all valid IEEE-754 32-bit floating point numbers
|
|
|
|
float64 the set of all valid IEEE-754 64-bit floating point numbers
|
|
|
|
float80 the set of all valid IEEE-754 80-bit floating point numbers
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Additionally, Go declares 4 basic types, uint, int, float, and double,
|
|
|
|
which are platform-specific. The bit width of these types corresponds to
|
2008-03-06 20:40:52 -07:00
|
|
|
the ``natural bit width'' for the respective types for the given
|
2008-03-04 23:18:16 -07:00
|
|
|
platform. For instance, int is usally the same as int32 on a 32-bit
|
|
|
|
architecture, or int64 on a 64-bit architecture. These types are by
|
|
|
|
definition platform-specific and should be used with the appropriate
|
|
|
|
caution.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Two reserved words, "true" and "false", represent the
|
2008-03-04 23:18:16 -07:00
|
|
|
corresponding boolean constant values.
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
There is also a polymorphic type, "any". The "any" type can represent
|
|
|
|
a value of any type.
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Numeric literals
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Integer literals take the usual C form, except for the absence of the
|
2008-03-26 00:53:07 -06:00
|
|
|
'U', 'L', etc. suffixes, and represent integer constants. Character
|
|
|
|
literals are also integer constants. Similarly, floating point
|
2008-03-04 23:18:16 -07:00
|
|
|
literals are also C-like, without suffixes and decimal only.
|
|
|
|
|
|
|
|
An integer constant represents an abstract integer value of arbitrary
|
|
|
|
precision. Only when an integer constant (or arithmetic expression
|
|
|
|
formed from integer constants) is bound to a typed variable
|
|
|
|
or constant is it required to fit into a particular size - that of the type
|
|
|
|
of the variable. In other words, integer constants and arithmetic
|
|
|
|
upon them is not subject to overflow; only finalization of integer
|
|
|
|
constants (and constant expressions) can cause overflow.
|
|
|
|
It is an error if the value of the constant or expression cannot be
|
|
|
|
represented correctly in the range of the type of the receiving
|
2008-03-26 00:53:07 -06:00
|
|
|
variable or constant. By extension, it is also possible to use
|
|
|
|
an integer as a floating constant (such as 1 instead of 1.0) if
|
|
|
|
it can be represented accurately, and vice versa (such as 1e9
|
|
|
|
instead of 1000000000).
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Floating point literals also represent an abstract, ideal floating
|
|
|
|
point value that is constrained only upon assignment.
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
sign = "+" | "-" .
|
|
|
|
int_lit = [ sign ] unsigned_int_lit .
|
2008-03-06 20:40:52 -07:00
|
|
|
unsigned_int_lit = decimal_int_lit | octal_int_lit | hex_int_lit .
|
2008-03-11 17:02:46 -06:00
|
|
|
decimal_int_lit = ( "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" )
|
2008-04-18 16:41:59 -06:00
|
|
|
{ dec_digit } .
|
2008-03-27 18:19:17 -06:00
|
|
|
octal_int_lit = "0" { oct_digit } .
|
2008-03-11 17:02:46 -06:00
|
|
|
hex_int_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } .
|
2008-03-27 18:19:17 -06:00
|
|
|
float_lit = [ sign ] ( fractional_lit | exponential_lit ) .
|
|
|
|
fractional_lit = { dec_digit } ( dec_digit "." | "." dec_digit )
|
|
|
|
{ dec_digit } [ exponent ] .
|
|
|
|
exponential_lit = dec_digit { dec_digit } exponent .
|
2008-04-18 16:41:59 -06:00
|
|
|
exponent = ( "e" | "E" ) [ sign ] dec_digit { dec_digit } .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
07
|
|
|
|
0xFF
|
|
|
|
-44
|
|
|
|
+3.24e-7
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
The string type
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
The string type represents the set of string values (strings).
|
2008-03-26 00:53:07 -06:00
|
|
|
Strings behave like arrays of bytes, with the following properties:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
- They are immutable: after creation, it is not possible to change the
|
2008-03-26 00:53:07 -06:00
|
|
|
contents of a string.
|
2008-03-04 23:18:16 -07:00
|
|
|
- No internal pointers: it is illegal to create a pointer to an inner
|
2008-03-26 00:53:07 -06:00
|
|
|
element of a string.
|
2008-04-18 16:41:59 -06:00
|
|
|
- They can be indexed: given string "s1", "s1[i]" is a byte value.
|
|
|
|
- They can be concatenated: given strings "s1" and "s2", "s1 + s2" is a value
|
|
|
|
combining the elements of "s1" and "s2" in sequence.
|
|
|
|
- Known length: the length of a string "s1" can be obtained by the function/
|
|
|
|
operator "len(s1)". The length of a string is the number of bytes within.
|
2008-03-04 23:18:16 -07:00
|
|
|
Unlike in C, there is no terminal NUL byte.
|
2008-03-16 22:47:38 -06:00
|
|
|
- Creation 1: a string can be created from an integer value by a conversion;
|
|
|
|
the result is a string containing the UTF-8 encoding of that code point.
|
2008-04-18 16:41:59 -06:00
|
|
|
"string('x')" yields "x"; "string(0x1234)" yields the equivalent of "\u1234"
|
2008-03-04 23:18:16 -07:00
|
|
|
- Creation 2: a string can by created from an array of integer values (maybe
|
|
|
|
just array of bytes) by a conversion
|
|
|
|
a [3]byte; a[0] = 'a'; a[1] = 'b'; a[2] = 'c'; string(a) == "abc";
|
|
|
|
|
|
|
|
|
|
|
|
Character and string literals
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
Character and string literals are almost the same as in C, with the
|
|
|
|
following differences:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
- The encoding is UTF-8
|
2008-03-04 23:18:16 -07:00
|
|
|
- `` strings exist; they do not interpret backslashes
|
2008-04-18 16:41:59 -06:00
|
|
|
- Octal character escapes are always 3 digits ("\077" not "\77")
|
|
|
|
- Hexadecimal character escapes are always 2 digits ("\x07" not "\x7")
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
This section is precise but can be skipped on first reading. The rules are:
|
2008-04-17 20:06:33 -06:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
char_lit = "'" ( unicode_value | byte_value ) "'" .
|
|
|
|
unicode_value = utf8_char | little_u_value | big_u_value | escaped_char .
|
|
|
|
byte_value = octal_byte_value | hex_byte_value .
|
|
|
|
octal_byte_value = "\" oct_digit oct_digit oct_digit .
|
|
|
|
hex_byte_value = "\" "x" hex_digit hex_digit .
|
|
|
|
little_u_value = "\" "u" hex_digit hex_digit hex_digit hex_digit .
|
|
|
|
big_u_value = "\" "U" hex_digit hex_digit hex_digit hex_digit
|
|
|
|
hex_digit hex_digit hex_digit hex_digit .
|
|
|
|
escaped_char = "\" ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | "\" | "'" | """ ) .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
A unicode_value takes one of four forms:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
* The UTF-8 encoding of a Unicode code point. Since Go source
|
|
|
|
text is in UTF-8, this is the obvious translation from input
|
|
|
|
text into Unicode characters.
|
2008-04-18 16:41:59 -06:00
|
|
|
* The usual list of C backslash escapes: "\n", "\t", etc.
|
|
|
|
* A `little u' value, such as "\u12AB". This represents the Unicode
|
2008-03-06 20:40:52 -07:00
|
|
|
code point with the corresponding hexadecimal value. It always
|
|
|
|
has exactly 4 hexadecimal digits.
|
2008-04-18 16:41:59 -06:00
|
|
|
* A `big U' value, such as "\U00101234". This represents the
|
2008-03-06 20:40:52 -07:00
|
|
|
Unicode code point with the corresponding hexadecimal value.
|
|
|
|
It always has exactly 8 hexadecimal digits.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Some values that can be represented this way are illegal because they
|
|
|
|
are not valid Unicode code points. These include values above
|
|
|
|
0x10FFFF and surrogate halves.
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
An octal_byte_value contains three octal digits. A hex_byte_value
|
2008-03-04 23:18:16 -07:00
|
|
|
contains two hexadecimal digits. (Note: This differs from C but is
|
|
|
|
simpler.)
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
It is erroneous for an octal_byte_value to represent a value larger than 255.
|
|
|
|
(By construction, a hex_byte_value cannot.)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A character literal is a form of unsigned integer constant. Its value
|
|
|
|
is that of the Unicode code point represented by the text between the
|
2008-03-27 23:11:10 -06:00
|
|
|
quotes.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
'a'
|
|
|
|
'ä'
|
|
|
|
'本'
|
|
|
|
'\t'
|
|
|
|
'\000'
|
|
|
|
'\007'
|
|
|
|
'\377'
|
|
|
|
'\x07'
|
|
|
|
'\xff'
|
|
|
|
'\u12e4'
|
|
|
|
'\U00101234'
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
String literals come in two forms: double-quoted and back-quoted.
|
|
|
|
Double-quoted strings have the usual properties; back-quoted strings
|
|
|
|
do not interpret backslashes at all.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
string_lit = raw_string_lit | interpreted_string_lit .
|
2008-04-18 16:41:59 -06:00
|
|
|
raw_string_lit = "`" { utf8_char } "`" .
|
|
|
|
interpreted_string_lit = """ { unicode_value | byte_value } """ .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A string literal has type 'string'. Its value is constructed by
|
|
|
|
taking the byte values formed by the successive elements of the
|
2008-03-26 00:53:07 -06:00
|
|
|
literal. For byte_values, these are the literal bytes; for
|
|
|
|
unicode_values, these are the bytes of the UTF-8 encoding of the
|
2008-03-06 20:40:52 -07:00
|
|
|
corresponding Unicode code points. Note that
|
2008-04-18 16:41:59 -06:00
|
|
|
"\u00FF"
|
2008-03-06 20:40:52 -07:00
|
|
|
and
|
2008-04-18 16:41:59 -06:00
|
|
|
"\xFF"
|
2008-03-06 20:40:52 -07:00
|
|
|
are
|
2008-03-04 23:18:16 -07:00
|
|
|
different strings: the first contains the two-byte UTF-8 expansion of
|
|
|
|
the value 255, while the second contains a single byte of value 255.
|
|
|
|
The same rules apply to raw string literals, except the contents are
|
|
|
|
uninterpreted UTF-8.
|
|
|
|
|
|
|
|
`abc`
|
|
|
|
`\n`
|
|
|
|
"hello, world\n"
|
|
|
|
"\n"
|
|
|
|
""
|
|
|
|
"Hello, world!\n"
|
|
|
|
"日本語"
|
|
|
|
"\u65e5本\U00008a9e"
|
|
|
|
"\xff\u00FF"
|
|
|
|
|
|
|
|
These examples all represent the same string:
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
"日本語" // UTF-8 input text
|
|
|
|
`日本語` // UTF-8 input text as a raw literal
|
|
|
|
"\u65e5\u672c\u8a9e" // The explicit Unicode code points
|
|
|
|
"\U000065e5\U0000672c\U00008a9e" // The explicit Unicode code points
|
|
|
|
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // The explicit UTF-8 bytes
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
The language does not canonicalize Unicode text or evaluate combining
|
|
|
|
forms. The text of source code is passed uninterpreted.
|
|
|
|
|
|
|
|
If the source code represents a character as two code points, such as
|
|
|
|
a combining form involving an accent and a letter, the result will be
|
|
|
|
an error if placed in a character literal (it is not a single code
|
|
|
|
point), and will appear as two code points if placed in a string
|
|
|
|
literal.
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
More about types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
The static type of a variable is the type defined by the variable's
|
|
|
|
declaration. At run-time, some variables, in particular those of
|
|
|
|
interface types, can assume a dynamic type, which may be
|
|
|
|
different at different times during execution. The dynamic type
|
|
|
|
of a variable is always compatible with the static type of the
|
|
|
|
variable.
|
|
|
|
|
|
|
|
At any given time, a variable or value has exactly one dynamic
|
|
|
|
type, which may be the same as the static type. (They will
|
2008-03-27 18:19:17 -06:00
|
|
|
differ only if the variable has an interface type or "any" type.)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Compound types may be constructed from other types by
|
|
|
|
assembling arrays, maps, channels, structures, and functions.
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Array, map and struct types are called structured types, all other types
|
2008-03-04 23:18:16 -07:00
|
|
|
are called unstructured. A structured type cannot contain itself.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Type = TypeName | ArrayType | ChannelType | InterfaceType |
|
|
|
|
FunctionType | MapType | StructType | PointerType .
|
|
|
|
TypeName = QualifiedIdent.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Array types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
[TODO: this section needs work regarding the precise difference between
|
2008-03-06 19:57:03 -07:00
|
|
|
static, open and dynamic arrays]
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
An array is a structured type consisting of a number of elements
|
|
|
|
all of the same type, called the element type. The number of
|
2008-03-04 23:18:16 -07:00
|
|
|
elements of an array is called its length. The elements of an array
|
2008-03-06 19:57:03 -07:00
|
|
|
are designated by indices which are integers between 0 and the length - 1.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
An array type specifies arrays with a given element type and
|
2008-03-06 19:57:03 -07:00
|
|
|
an optional array length. If the length is present, it is part of the type.
|
|
|
|
Arrays without a length specification are called open arrays.
|
|
|
|
Any array may be assigned to an open array variable with the
|
|
|
|
same element type. Typically, open arrays are used as
|
|
|
|
formal parameters for functions.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ArrayType = "[" [ ArrayLength ] "]" ElementType .
|
2008-03-06 22:24:57 -07:00
|
|
|
ArrayLength = Expression .
|
|
|
|
ElementType = Type .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
[] uint8
|
2008-03-06 00:00:44 -07:00
|
|
|
[2*n] int
|
2008-03-04 23:18:16 -07:00
|
|
|
[64] struct { x, y: int32; }
|
|
|
|
[1000][1000] float64
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
The length of an array can be discovered at run time (or compile time, if
|
|
|
|
its length is a constant) using the built-in special function len():
|
2008-03-06 19:57:03 -07:00
|
|
|
|
|
|
|
len(a)
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Map types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A map is a structured type consisting of a variable number of entries
|
|
|
|
called (key, value) pairs. For a given map,
|
|
|
|
the keys and values must each be of a specific type.
|
|
|
|
Upon creation, a map is empty and values may be added and removed
|
|
|
|
during execution. The number of entries in a map is called its length.
|
2008-03-06 00:00:44 -07:00
|
|
|
A map whose value type is 'any' can store values of all types.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
MapType = "map" "[" KeyType "]" ValueType .
|
2008-03-06 20:40:52 -07:00
|
|
|
KeyType = Type .
|
2008-03-11 17:02:46 -06:00
|
|
|
ValueType = Type | "any" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
map [string] int
|
|
|
|
map [struct { pid int; name string }] *chan Buffer
|
2008-03-06 00:00:44 -07:00
|
|
|
map [string] any
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Struct types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Struct types are similar to C structs.
|
|
|
|
|
|
|
|
Each field of a struct represents a variable within the data
|
|
|
|
structure.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
StructType = "struct" "{" [ FieldDeclList [ ";" ] ] "}" .
|
2008-03-12 14:12:40 -06:00
|
|
|
FieldDeclList = FieldDecl { ";" FieldDecl } .
|
2008-03-07 19:01:09 -07:00
|
|
|
FieldDecl = IdentifierList Type .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// An empty struct.
|
|
|
|
struct {}
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// A struct with 5 fields.
|
|
|
|
struct {
|
|
|
|
x, y int;
|
|
|
|
u float;
|
|
|
|
a []int;
|
|
|
|
f func();
|
|
|
|
}
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Compound Literals
|
|
|
|
----
|
|
|
|
|
|
|
|
Literals for compound data structures consist of the type of the constant
|
|
|
|
followed by a parenthesized expression list. In effect, they are a
|
|
|
|
conversion from expression list to compound value.
|
|
|
|
|
|
|
|
|
|
|
|
Array literals
|
|
|
|
----
|
|
|
|
|
|
|
|
Array literals represent array values. All the contained expressions must
|
|
|
|
be of the same type, which is the element type of the resulting array.
|
|
|
|
|
|
|
|
ArrayLit = ArrayType "(" [ ExpressionList ] ")" .
|
|
|
|
|
|
|
|
[]int()
|
|
|
|
[]int(1, 2, 3)
|
|
|
|
[]string("x", "y")
|
|
|
|
|
|
|
|
Unresolved issues: Are elements converted? What about length?
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Map Literals
|
|
|
|
----
|
|
|
|
|
|
|
|
Map literals represent map values. They comprise a list of (key, value)
|
|
|
|
pairs written as successive values.
|
|
|
|
All keys must have the same type; all values must have the same type.
|
|
|
|
|
|
|
|
|
|
|
|
MapLit = MapType "(" KeyValueList ")" .
|
|
|
|
KeyValueList = [ KeyValue { "," KeyValue } ].
|
|
|
|
KeyValue = Expression "," Expression .
|
|
|
|
|
|
|
|
[string]map int("one",1, "two",2)
|
|
|
|
[int]map bool(2,true, 3,true, 5,true, 7,true)
|
|
|
|
|
|
|
|
Unresolved issues: Are elements converted?
|
|
|
|
Colon for a separator or comma?
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
Struct literals
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Struct literals represent struct constants. They comprise a list of
|
|
|
|
expressions that represent the individual fields of a struct. The
|
|
|
|
individual expressions must match those of the specified struct type.
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
StructLit = StructType "(" [ ExpressionList ] ")" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
Point(2, 3)
|
|
|
|
ColoredPoint(4, 4, "green")
|
2008-03-26 00:53:07 -06:00
|
|
|
struct { a, b int } (7, 8)
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Pointer types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Pointer types are similar to those in C.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
PointerType = "*" Type.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
We do not allow pointer arithmetic of any kind.
|
|
|
|
|
|
|
|
*int
|
2008-03-26 00:53:07 -06:00
|
|
|
*map[string] *chan
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
There are no pointer literals.
|
|
|
|
|
|
|
|
|
|
|
|
Channel types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A channel provides a mechanism for two concurrently executing functions
|
2008-03-27 18:19:17 -06:00
|
|
|
to synchronize execution and exchange values of a specified type.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Upon creation, a channel can be used both to send and to receive.
|
|
|
|
By conversion or assignment, it may be restricted only to send or
|
|
|
|
to receive; such a restricted channel
|
2008-03-04 23:18:16 -07:00
|
|
|
is called a 'send channel' or a 'receive channel'.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ChannelType = "chan" [ "<" | ">" ] ValueType .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
chan any // a generic channel
|
|
|
|
chan int // a channel that can exchange only ints
|
|
|
|
chan> float // a channel that can only be used to send floats
|
|
|
|
chan< any // a channel that can receive (only) values of any type
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Channel variables always have type pointer to channel.
|
2008-03-26 00:53:07 -06:00
|
|
|
It is an error to attempt to use a channel value and in
|
|
|
|
particular to dereference a channel pointer.
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
var ch *chan int;
|
|
|
|
ch = new(chan int); // new returns type *chan int
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
There are no channel literals.
|
|
|
|
|
|
|
|
|
|
|
|
Function types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A function type denotes the set of all functions with the same signature.
|
|
|
|
|
|
|
|
A method is a function with a receiver, which is of type pointer to struct.
|
|
|
|
|
|
|
|
Functions can return multiple values simultaneously.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
FunctionType = "func" AnonymousSignature .
|
|
|
|
AnonymousSignature = [ Receiver "." ] Parameters [ Result ] .
|
|
|
|
Receiver = "(" identifier Type ")" .
|
|
|
|
Parameters = "(" [ ParameterList ] ")" .
|
|
|
|
ParameterList = ParameterSection { "," ParameterSection } .
|
2008-04-29 17:27:11 -06:00
|
|
|
ParameterSection = IdentifierList Type .
|
2008-03-11 17:02:46 -06:00
|
|
|
Result = Type | "(" ParameterList ")" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// Function types
|
|
|
|
func ()
|
|
|
|
func (a, b int, z float) bool
|
|
|
|
func (a, b int, z float) (success bool)
|
|
|
|
func (a, b int, z float) (success bool, result float)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// Method types
|
|
|
|
func (p *T) . ()
|
|
|
|
func (p *T) . (a, b int, z float) bool
|
|
|
|
func (p *T) . (a, b int, z float) (success bool)
|
|
|
|
func (p *T) . (a, b int, z float) (success bool, result float)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
A variable can hold only a pointer to a function, not a function value.
|
|
|
|
In particular, v := func() {} creates a variable of type *func(). To call the
|
|
|
|
function referenced by v, one writes v(). It is illegal to dereference a
|
|
|
|
function pointer.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Function Literals
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Function literals represent anonymous functions.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
FunctionLit = FunctionType Block .
|
2008-03-11 17:02:46 -06:00
|
|
|
Block = "{" [ StatementList [ ";" ] ] "}" .
|
2008-03-11 15:37:16 -06:00
|
|
|
|
|
|
|
The scope of an identifier declared within a block extends
|
|
|
|
from the declaration of the identifier (that is, the position
|
|
|
|
immediately after the identifier) to the end of the block.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A function literal can be invoked
|
|
|
|
or assigned to a variable of the corresponding function pointer type.
|
2008-03-06 00:00:44 -07:00
|
|
|
For now, a function literal can reference only its parameters, global
|
|
|
|
variables, and variables declared within the function literal.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// Function literal
|
|
|
|
func (a, b int, z float) bool { return a*b < int(z); }
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
// Method literal
|
|
|
|
func (p *T) . (a, b int, z float) bool { return a*b < int(z) + p.x; }
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Unresolved issues: Are there method literals? How do you use them?
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
Methods
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A method is a function bound to a particular struct type T. When defined,
|
|
|
|
a method indicates the type of the struct by declaring a receiver of type
|
|
|
|
*T. For instance, given type Point
|
|
|
|
|
|
|
|
type Point struct { x, y float }
|
|
|
|
|
|
|
|
the declaration
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
func (p *Point) distance(scale float) float {
|
2008-03-06 00:00:44 -07:00
|
|
|
return scale * (p.x*p.x + p.y*p.y);
|
|
|
|
}
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
creates a method of type Point. Note that methods are not declared
|
2008-03-06 00:00:44 -07:00
|
|
|
within their struct type declaration. They may appear anywhere and
|
|
|
|
may be forward-declared for commentary.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
When invoked, a method behaves like a function whose first argument
|
|
|
|
is the receiver, but at the call site the receiver is bound to the method
|
|
|
|
using the notation
|
|
|
|
|
|
|
|
receiver.method()
|
|
|
|
|
|
|
|
For instance, given a Point variable pt, one may call
|
|
|
|
|
|
|
|
pt.distance(3.5)
|
|
|
|
|
|
|
|
|
|
|
|
Interface of a struct
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
The interface of a struct is defined to be the unordered set of methods
|
|
|
|
associated with that struct.
|
|
|
|
|
|
|
|
|
|
|
|
Interface types
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
An interface type denotes a set of methods.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
InterfaceType = "interface" "{" [ MethodDeclList [ ";" ] ] "}" .
|
|
|
|
MethodDeclList = MethodDecl { ";" MethodDecl } .
|
2008-03-07 19:01:09 -07:00
|
|
|
MethodDecl = identifier Parameters [ Result ] .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
// A basic file interface.
|
|
|
|
type File interface {
|
|
|
|
Read(b Buffer) bool;
|
|
|
|
Write(b Buffer) bool;
|
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
Any struct whose interface has, possibly as a subset, the complete
|
|
|
|
set of methods of an interface I is said to implement interface I.
|
|
|
|
For instance, if two struct types S1 and S2 have the methods
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
func (p *T) Read(b Buffer) bool { return ... }
|
|
|
|
func (p *T) Write(b Buffer) bool { return ... }
|
|
|
|
func (p *T) Close() { ... }
|
|
|
|
|
|
|
|
then the File interface is implemented by both S1 and S2, regardless of
|
|
|
|
what other methods S1 and S2 may have or share.
|
|
|
|
|
|
|
|
All struct types implement the empty interface:
|
|
|
|
|
|
|
|
interface {}
|
|
|
|
|
|
|
|
In general, a struct type implements an arbitrary number of interfaces.
|
|
|
|
For instance, if we have
|
|
|
|
|
|
|
|
type Lock interface {
|
|
|
|
lock();
|
|
|
|
unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
and S1 and S2 also implement
|
|
|
|
|
|
|
|
func (p *T) lock() { ... }
|
|
|
|
func (p *T) unlock() { ... }
|
|
|
|
|
|
|
|
they implement the Lock interface as well as the File interface.
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
It is legal to assign a pointer to a struct to a variable of
|
|
|
|
compatible interface type. It is legal to assign an interface
|
|
|
|
variable to any struct pointer variable but if the struct type is
|
|
|
|
incompatible the result will be nil.
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
There are no interface literals.
|
|
|
|
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
The polymorphic "any" type
|
|
|
|
----
|
|
|
|
|
|
|
|
Given a variable of type "any", one can store any value into it by
|
|
|
|
plain assignment or implicitly, such as through a function parameter
|
|
|
|
or channel operation. Given an "any" variable v storing an underlying
|
|
|
|
value of type T, one may:
|
|
|
|
|
|
|
|
- copy v's value to another variable of type "any"
|
|
|
|
- extract the stored value by an explicit conversion operation T(v)
|
|
|
|
- copy v's value to a variable of type T
|
|
|
|
|
|
|
|
Attempts to convert/extract to an incompatible type will yield nil.
|
|
|
|
|
|
|
|
No other operations are defined (yet).
|
|
|
|
|
|
|
|
Note that type
|
2008-04-18 16:41:59 -06:00
|
|
|
interface {}
|
2008-03-27 18:19:17 -06:00
|
|
|
is a special case that can match any struct type, while type
|
2008-04-18 16:41:59 -06:00
|
|
|
any
|
2008-03-27 18:19:17 -06:00
|
|
|
can match any type at all, including basic types, arrays, etc.
|
|
|
|
|
|
|
|
TODO: details about reflection
|
|
|
|
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
Equivalence of types
|
|
|
|
---
|
|
|
|
|
|
|
|
Types are structurally equivalent: Two types are equivalent ('equal') if they
|
|
|
|
are constructed the same way from equivalent types.
|
|
|
|
|
|
|
|
For instance, all variables declared as "*int" have equivalent type,
|
|
|
|
as do all variables declared as "map [string] chan int".
|
|
|
|
|
|
|
|
More precisely, two struct types are equivalent if they have exactly the same fields
|
|
|
|
in the same order, with equal field names and types. For all other composite types,
|
|
|
|
the types of the components must be equivalent. Additionally, for equivalent arrays,
|
|
|
|
the lengths must be equal (or absent), and for channel types the mode must be equal
|
|
|
|
(">", "<", or none). The names of receivers, parameters, or result values of functions
|
|
|
|
are ignored for the purpose of type equivalence.
|
|
|
|
|
|
|
|
For instance, the struct type
|
|
|
|
|
|
|
|
struct {
|
|
|
|
a int;
|
|
|
|
b int;
|
|
|
|
f *func (m *[32] float, x int, y int) bool
|
|
|
|
}
|
|
|
|
|
|
|
|
is equivalent to
|
|
|
|
|
|
|
|
struct {
|
|
|
|
a, b int;
|
|
|
|
f *F
|
|
|
|
}
|
|
|
|
|
|
|
|
where "F" is declared as "func (a *[30 + 2] float, b, c int) (ok bool)".
|
|
|
|
|
|
|
|
Finally, two interface types are equivalent if they both declare the same set of
|
|
|
|
methods: For each method in the first interface type there is a method in the
|
|
|
|
second interface type with the same method name and equivalent signature, and
|
|
|
|
vice versa. Note that the declaration order of the methods is not relevant.
|
|
|
|
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
Literals
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Literal = BasicLit | CompoundLit .
|
2008-03-11 19:07:22 -06:00
|
|
|
BasicLit = char_lit | string_lit | int_lit | float_lit | "nil" .
|
2008-03-06 20:40:52 -07:00
|
|
|
CompoundLit = ArrayLit | MapLit | StructLit | FunctionLit .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A declaration associates a name with a language entity such as a type,
|
|
|
|
constant, variable, or function.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | ExportDecl .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Const declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A constant declaration gives a name to the value of a constant expression.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ConstDecl = "const" ( ConstSpec | "(" ConstSpecList [ ";" ] ")" ).
|
|
|
|
ConstSpec = identifier [ Type ] "=" Expression .
|
|
|
|
ConstSpecList = ConstSpec { ";" ConstSpec }.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
const pi float = 3.14159265
|
|
|
|
const e = 2.718281828
|
|
|
|
const (
|
|
|
|
one int = 1;
|
|
|
|
two = 3
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Type declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A type declaration introduces a name as a shorthand for a type.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
TypeDecl = "type" ( TypeSpec | "(" TypeSpecList [ ";" ] ")" ).
|
2008-03-06 20:40:52 -07:00
|
|
|
TypeSpec = identifier Type .
|
2008-03-11 17:02:46 -06:00
|
|
|
TypeSpecList = TypeSpec { ";" TypeSpec }.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
type IntArray [16] int
|
|
|
|
type (
|
|
|
|
Point struct { x, y float };
|
|
|
|
Polar Point
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Variable declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A variable declaration creates a variable and gives it a type and a name.
|
|
|
|
It may optionally give the variable an initial value; in some forms of
|
|
|
|
declaration the type of the initial value defines the type of the variable.
|
|
|
|
|
2008-03-11 17:40:47 -06:00
|
|
|
VarDecl = "var" ( VarSpec | "(" VarSpecList [ ";" ] ")" ) .
|
2008-03-11 17:02:46 -06:00
|
|
|
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
|
|
|
|
VarSpecList = VarSpec { ";" VarSpec } .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
var i int
|
|
|
|
var u, v, w float
|
|
|
|
var k = 0
|
|
|
|
var x, y float = -1.0, -2.0
|
|
|
|
var (
|
|
|
|
i int;
|
|
|
|
u, v = 2.0, 3.0
|
|
|
|
)
|
|
|
|
|
|
|
|
If the expression list is present, it must have the same number of elements
|
|
|
|
as there are variables in the variable specification.
|
|
|
|
|
|
|
|
The syntax
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
SimpleVarDecl = identifier ":=" Expression .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
is shorthand for
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
var identifer = Expression.
|
|
|
|
|
|
|
|
i := 0
|
|
|
|
f := func() int { return 7; }
|
|
|
|
ch := new(chan int);
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Also, in some contexts such as if or for statements,
|
|
|
|
this construct can be used to
|
2008-03-04 23:18:16 -07:00
|
|
|
declare local temporary variables.
|
|
|
|
|
|
|
|
|
|
|
|
Function and method declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Functions and methods have a special declaration syntax, slightly
|
|
|
|
different from the type syntax because an identifier must be present
|
2008-03-26 00:53:07 -06:00
|
|
|
in the signature. Functions and methods can only be declared
|
2008-03-06 00:00:44 -07:00
|
|
|
at the global level.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
FunctionDecl = "func" NamedSignature ( ";" | Block ) .
|
2008-03-06 20:40:52 -07:00
|
|
|
NamedSignature = [ Receiver ] identifier Parameters [ Result ] .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
func min(x int, y int) int {
|
|
|
|
if x < y {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
func foo(a, b int, z float) bool {
|
2008-03-04 23:18:16 -07:00
|
|
|
return a*b < int(z);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
A method is a function that also declares a receiver.
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
func (p *T) foo(a, b int, z float) bool {
|
2008-03-04 23:18:16 -07:00
|
|
|
return a*b < int(z) + p.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Point) Length() float {
|
|
|
|
return Math.sqrt(p.x * p.x + p.y * p.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Point) Scale(factor float) {
|
|
|
|
p.x = p.x * factor;
|
|
|
|
p.y = p.y * factor;
|
|
|
|
}
|
|
|
|
|
|
|
|
Functions and methods can be forward declared by omitting the body:
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
func foo(a, b int, z float) bool;
|
|
|
|
func (p *T) foo(a, b int, z float) bool;
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
2008-04-17 18:03:29 -06:00
|
|
|
Initial values
|
|
|
|
----
|
|
|
|
|
|
|
|
When memory is allocated to store a value, either through a declaration
|
|
|
|
or new(), and no explicit initialization is provided, the memory is
|
|
|
|
given a default initialization. Each element of such a value is
|
|
|
|
set to the ``zero'' for that type: 0 for integers, 0.0 for floats, and
|
|
|
|
nil for pointers. This intialization is done recursively, so for
|
|
|
|
instance each element of an array of integers will be set to 0 if no
|
|
|
|
other value is specified.
|
|
|
|
|
|
|
|
These two simple declarations are equivalent:
|
|
|
|
|
|
|
|
var i int;
|
|
|
|
var i int = 0;
|
|
|
|
|
|
|
|
After
|
|
|
|
|
|
|
|
type T struct { i int; f float; next *T };
|
|
|
|
t := new(T);
|
|
|
|
|
|
|
|
the following holds:
|
|
|
|
|
|
|
|
t.i == 0
|
|
|
|
t.f == 0.0
|
|
|
|
t.next == nil
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
Export declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
Global identifiers may be exported, thus making the
|
2008-03-04 23:18:16 -07:00
|
|
|
exported identifer visible outside the package. Another package may
|
|
|
|
then import the identifier to use it.
|
|
|
|
|
|
|
|
Export declarations must only appear at the global level of a
|
2008-03-26 00:53:07 -06:00
|
|
|
compilation unit and can name only globally-visible identifiers.
|
|
|
|
That is, one can export global functions, types, and so on but not
|
|
|
|
local variables or structure fields.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Exporting an identifier makes the identifier visible externally to the
|
|
|
|
package. If the identifier represents a type, the type structure is
|
|
|
|
exported as well. The exported identifiers may appear later in the
|
|
|
|
source than the export directive itself, but it is an error to specify
|
|
|
|
an identifier not declared anywhere in the source file containing the
|
|
|
|
export directive.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ExportDecl = "export" ExportIdentifier { "," ExportIdentifier } .
|
2008-03-06 20:40:52 -07:00
|
|
|
ExportIdentifier = QualifiedIdent .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
export sin, cos
|
2008-03-26 00:53:07 -06:00
|
|
|
export math.abs
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
TODO: complete this section
|
|
|
|
|
|
|
|
TODO: export as a mechanism for public and private struct fields?
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Expressions
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
Expression syntax is based on that of C but with fewer precedence levels.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Expression = BinaryExpr | UnaryExpr | PrimaryExpr .
|
|
|
|
BinaryExpr = Expression binary_op Expression .
|
|
|
|
UnaryExpr = unary_op Expression .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
PrimaryExpr =
|
2008-03-11 17:02:46 -06:00
|
|
|
identifier | Literal | "(" Expression ")" | "iota" |
|
2008-03-11 19:07:22 -06:00
|
|
|
Call | Conversion | Allocation |
|
2008-04-17 20:06:33 -06:00
|
|
|
Expression "[" Expression [ ":" Expression ] "]" | Expression "." identifier |
|
|
|
|
Expression "." "(" Type ")" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
Call = Expression "(" [ ExpressionList ] ")" .
|
2008-04-27 19:32:47 -06:00
|
|
|
Conversion = TypeName "(" Expression ")" |
|
|
|
|
"convert" "(" Type "," Expression ")" .
|
2008-03-17 20:05:07 -06:00
|
|
|
Allocation = "new" "(" Type [ "," Expression ] ")" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
binary_op = log_op | rel_op | add_op | mul_op .
|
2008-03-11 17:02:46 -06:00
|
|
|
log_op = "||" | "&&" .
|
|
|
|
rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=".
|
|
|
|
add_op = "+" | "-" | "|" | "^".
|
|
|
|
mul_op = "*" | "/" | "%" | "<<" | ">>" | "&".
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
unary_op = "+" | "-" | "!" | "^" | "<" | ">" | "*" | "&" .
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-04-17 20:06:33 -06:00
|
|
|
Field selection and type assertions ('.') bind tightest, followed by indexing ('[]')
|
|
|
|
and then calls and conversions. The remaining precedence levels are as follows
|
|
|
|
(in increasing precedence order):
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Precedence Operator
|
2008-04-18 16:41:59 -06:00
|
|
|
1 ||
|
|
|
|
2 &&
|
|
|
|
3 == != < <= > >=
|
|
|
|
4 + - | ^
|
|
|
|
5 * / % << >> &
|
|
|
|
6 + - ! ^ < > * & (unary)
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
For integer values, / and % satisfy the following relationship:
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
(a / b) * b + a % b == a
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
and
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
(a / b) is "truncated towards zero".
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
There are no implicit type conversions except for
|
2008-03-26 00:53:07 -06:00
|
|
|
constants and literals. In particular, unsigned and signed integer
|
|
|
|
variables cannot be mixed in an expression without explicit conversion.
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
The shift operators implement arithmetic shifts for signed integers
|
|
|
|
and logical shifts for unsigned integers. The properties of negative
|
2008-03-06 19:57:03 -07:00
|
|
|
shift counts are undefined. Unary '^' corresponds to C '~' (bitwise
|
|
|
|
complement).
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
There is no '->' operator. Given a pointer p to a struct, one writes
|
2008-04-18 16:41:59 -06:00
|
|
|
p.f
|
2008-03-26 00:53:07 -06:00
|
|
|
to access field f of the struct. Similarly, given an array or map
|
|
|
|
pointer, one writes
|
2008-04-18 16:41:59 -06:00
|
|
|
p[i]
|
2008-03-26 00:53:07 -06:00
|
|
|
to access an element. Given a function pointer, one writes
|
2008-04-18 16:41:59 -06:00
|
|
|
p()
|
2008-03-26 00:53:07 -06:00
|
|
|
to call the function.
|
2008-03-06 19:57:03 -07:00
|
|
|
|
|
|
|
Other operators behave as in C.
|
|
|
|
|
2008-04-17 18:03:29 -06:00
|
|
|
The "iota" keyword is discussed in a later section.
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Examples of primary expressions
|
2008-03-06 19:57:03 -07:00
|
|
|
|
|
|
|
x
|
|
|
|
2
|
|
|
|
(s + ".txt")
|
|
|
|
f(3.1415, true)
|
|
|
|
Point(1, 2)
|
2008-03-17 20:05:07 -06:00
|
|
|
new([]int, 100)
|
2008-03-06 19:57:03 -07:00
|
|
|
m["foo"]
|
|
|
|
s[i : j + 1]
|
|
|
|
obj.color
|
|
|
|
Math.sin
|
|
|
|
f.p[i].x()
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Examples of general expressions
|
2008-03-06 19:57:03 -07:00
|
|
|
|
|
|
|
+x
|
|
|
|
23 + 3*x[i]
|
|
|
|
x <= f()
|
|
|
|
^a >> b
|
|
|
|
f() || g()
|
|
|
|
x == y + 1 && <chan_ptr > 0
|
2008-04-17 18:03:29 -06:00
|
|
|
|
|
|
|
|
|
|
|
The nil value
|
|
|
|
----
|
|
|
|
|
|
|
|
The keyword
|
|
|
|
nil
|
|
|
|
represents the ``zero'' value for a pointer type or interface type.
|
|
|
|
|
|
|
|
The only operations allowed for nil are to assign it to a pointer or
|
|
|
|
interface value and to compare it for equality or inquality with a
|
|
|
|
pointer or interface value.
|
|
|
|
|
|
|
|
var p *int;
|
|
|
|
if p != nil {
|
|
|
|
print p
|
|
|
|
} else {
|
|
|
|
print "p points nowhere"
|
|
|
|
}
|
|
|
|
|
|
|
|
By default, pointers are initialized to nil.
|
|
|
|
|
|
|
|
TODO: how does this definition jibe with using nil to specify
|
|
|
|
conversion failure if the result is not of pointer type, such
|
|
|
|
as an any variable holding an int?
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-04-17 18:03:29 -06:00
|
|
|
Allocation
|
|
|
|
----
|
|
|
|
|
|
|
|
The builtin-function new() allocates storage. The function takes a
|
|
|
|
parenthesized operand list comprising the type of the value to
|
|
|
|
allocate, optionally followed by type-specific expressions that
|
|
|
|
influence the allocation. The invocation returns a pointer to the
|
|
|
|
memory. The memory is initialized as described in the section on
|
|
|
|
initial values.
|
|
|
|
|
|
|
|
For instance,
|
|
|
|
|
|
|
|
type S struct { a int; b float }
|
|
|
|
new(int32)
|
|
|
|
|
|
|
|
allocates storage for an S, initializes it (a=0, b=0.0), and returns a
|
|
|
|
value of type *S pointing to that storage.
|
|
|
|
|
|
|
|
The only defined parameters affect sizes for allocating arrays,
|
|
|
|
buffered channels, and maps.
|
|
|
|
|
|
|
|
ap := new([]int, 10); # a pointer to an array of 10 ints
|
|
|
|
aap := new([][]int, 5, 10); # a pointer to an array of 5 arrays of 10 ints
|
|
|
|
c := new(chan int, 10); # a pointer to a channel with a buffer size of 10
|
|
|
|
m := new(map[string] int, 100); # a pointer to a map with space for 100 elements preallocated
|
|
|
|
|
|
|
|
TODO: argument order for dimensions in multidimensional arrays
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-04-27 19:32:47 -06:00
|
|
|
|
|
|
|
Conversions
|
|
|
|
----
|
|
|
|
|
|
|
|
There are three ways to convert a value from one type to another.
|
|
|
|
|
|
|
|
The most general is a call to the intrinsic special function "convert"
|
|
|
|
with arguments the type name and the value to be converted.
|
|
|
|
|
|
|
|
var i int = convert(int, PI * 1000.0);
|
|
|
|
chars_as_ints := convert([]int, "now is the time");
|
|
|
|
|
|
|
|
If the destination type is a known type name, the conversion can be
|
|
|
|
rewritten to look syntactically like a call to a function with that
|
|
|
|
name.
|
|
|
|
|
|
|
|
i := int(PI * 1000.0);
|
|
|
|
s := AStructType(an_interface_variable);
|
|
|
|
|
|
|
|
A conversion can be written as a parenthesized type after a period.
|
|
|
|
Although intended for ease of conversion within a method call chain,
|
|
|
|
this form works in any expression context.
|
|
|
|
|
|
|
|
var s *AStructType = vec.index(2).(*AStructType);
|
|
|
|
fld := vec.index(2).(*AStructType).field;
|
|
|
|
f := 1000.(float);
|
|
|
|
|
|
|
|
TODO: are there parameters to any conversions? go.y has oexpr_list as the
|
|
|
|
contents of a TypeName() conversion; i expected expr instead and that's what
|
|
|
|
the others have.
|
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
The constant generator 'iota'
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-04-28 17:19:59 -06:00
|
|
|
Within a declaration, the keyword 'iota' represents successive
|
|
|
|
elements of an integer sequence.
|
|
|
|
It is reset to zero whenever the keyword 'const'
|
|
|
|
introduces a new declaration and increments as each identifier
|
|
|
|
is declared. For instance, 'iota' can be used to construct
|
2008-03-06 19:57:03 -07:00
|
|
|
a set of related constants:
|
|
|
|
|
|
|
|
const (
|
|
|
|
enum0 = iota; // sets enum0 to 0, etc.
|
|
|
|
enum1 = iota;
|
|
|
|
enum2 = iota
|
|
|
|
)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
const (
|
|
|
|
a = 1 << iota; // sets a to 1 (iota has been reset)
|
|
|
|
b = 1 << iota; // sets b to 2
|
|
|
|
c = 1 << iota; // sets c to 4
|
|
|
|
)
|
|
|
|
|
|
|
|
const x = iota; // sets x to 0
|
|
|
|
const y = iota; // sets y to 0
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-28 17:19:59 -06:00
|
|
|
TODO: should iota work in var, type, func decls too?
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Statements control execution.
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Statement =
|
2008-03-10 17:23:01 -06:00
|
|
|
[ LabelDecl ] ( StructuredStat | UnstructuredStat ) .
|
|
|
|
|
|
|
|
StructuredStat =
|
2008-03-27 22:42:25 -06:00
|
|
|
Block | IfStat | SwitchStat | SelectStat | ForStat | RangeStat .
|
2008-03-10 17:23:01 -06:00
|
|
|
|
|
|
|
UnstructuredStat =
|
2008-03-11 17:40:47 -06:00
|
|
|
Declaration | SimpleVarDecl |
|
2008-03-10 17:23:01 -06:00
|
|
|
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat .
|
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
SimpleStat =
|
|
|
|
ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
|
2008-03-10 17:23:01 -06:00
|
|
|
|
|
|
|
|
|
|
|
Statement lists
|
|
|
|
----
|
|
|
|
|
|
|
|
Semicolons are used to separate individual statements of a statement list.
|
|
|
|
They are optional after a statement that ends with a closing curly brace '}'.
|
|
|
|
|
|
|
|
StatementList =
|
|
|
|
StructuredStat |
|
|
|
|
UnstructuredStat |
|
|
|
|
StructuredStat [ ";" ] StatementList |
|
|
|
|
UnstructuredStat ";" StatementList .
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
TODO: define optional semicolons precisely
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Expression statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
ExpressionStat = Expression .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
f(x+y)
|
|
|
|
|
|
|
|
|
|
|
|
IncDec statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
IncDecStat = Expression ( "++" | "--" ) .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
a[i]++
|
|
|
|
|
|
|
|
Note that ++ and -- are not operators for expressions.
|
|
|
|
|
|
|
|
|
|
|
|
Assignments
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
Assignment = SingleAssignment | TupleAssignment | Send .
|
2008-03-07 00:06:05 -07:00
|
|
|
SingleAssignment = PrimaryExpr assign_op Expression .
|
|
|
|
TupleAssignment = PrimaryExprList assign_op ExpressionList .
|
|
|
|
PrimaryExprList = PrimaryExpr { "," PrimaryExpr } .
|
2008-03-11 17:02:46 -06:00
|
|
|
Send = ">" Expression "=" Expression .
|
2008-03-06 20:40:52 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
assign_op = [ add_op | mul_op ] "=" .
|
2008-03-06 19:57:03 -07:00
|
|
|
|
2008-03-07 00:06:05 -07:00
|
|
|
The left-hand side must be an l-value such as a variable, pointer indirection,
|
2008-03-04 23:18:16 -07:00
|
|
|
or an array indexing.
|
|
|
|
|
|
|
|
x = 1
|
|
|
|
*p = f()
|
|
|
|
a[i] = 23
|
2008-03-06 19:57:03 -07:00
|
|
|
|
|
|
|
As in C, arithmetic binary operators can be combined with assignments:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
j <<= 2
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A tuple assignment assigns the individual elements of a multi-valued operation,
|
2008-03-26 00:53:07 -06:00
|
|
|
such as function evaluation or some channel and map operations, into individual
|
2008-03-06 00:00:44 -07:00
|
|
|
variables. For instance, a tuple assignment such as
|
|
|
|
|
|
|
|
v1, v2, v3 = e1, e2, e3
|
|
|
|
|
|
|
|
assigns the expressions e1, e2, e3 to temporaries and then assigns the temporaries
|
|
|
|
to the variables v1, v2, v3. Thus
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
a, b = b, a
|
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
exchanges the values of a and b. The tuple assignment
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
x, y = f()
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
calls the function f, which must return two values, and assigns them to x and y.
|
2008-03-06 00:00:44 -07:00
|
|
|
As a special case, retrieving a value from a map, when written as a two-element
|
|
|
|
tuple assignment, assign a value and a boolean. If the value is present in the map,
|
|
|
|
the value is assigned and the second, boolean variable is set to true. Otherwise,
|
|
|
|
the variable is unchanged, and the boolean value is set to false.
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
value, present = map_var[key]
|
2008-03-06 00:00:44 -07:00
|
|
|
|
|
|
|
Analogously, receiving a value from a channel can be written as a tuple assignment.
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
value, success = <chan_var
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
If the receive operation would block, the boolean is set to false.
|
|
|
|
This provides a mechanism to avoid blocking on a receive operation.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Sending on a channel is a form of assignment. The left hand side expression
|
|
|
|
must denote a channel pointer value.
|
|
|
|
|
|
|
|
>chan_ptr = value
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-07 00:06:05 -07:00
|
|
|
In assignments, the type of the expression must match the type of the left-hand side.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Go statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A go statement starts the execution of a function as an independent
|
|
|
|
concurrent thread of control within the same address space. Unlike
|
|
|
|
with a function, the next line of the program does not wait for the
|
|
|
|
function to complete.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
GoStat = "go" Call .
|
2008-03-06 20:40:52 -07:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
go Server()
|
2008-03-26 00:53:07 -06:00
|
|
|
go func(ch chan> bool) { for { sleep(10); >ch = true; }} (c)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Return statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A return statement terminates execution of the containing function
|
|
|
|
and optionally provides a result value or values to the caller.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ReturnStat = "return" [ ExpressionList ] .
|
2008-03-06 20:40:52 -07:00
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
There are two ways to return values from a function. The first is to
|
|
|
|
explicitly list the return value or values in the return statement:
|
|
|
|
|
2008-03-11 17:40:47 -06:00
|
|
|
func simple_f() int {
|
2008-03-04 23:18:16 -07:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
func complex_f1() (float, float) {
|
2008-03-04 23:18:16 -07:00
|
|
|
return -7.0, -4.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
The second is to provide names for the return values and assign them
|
|
|
|
explicitly in the function; the return statement will then provide no
|
|
|
|
values:
|
|
|
|
|
|
|
|
func complex_f2() (re float, im float) {
|
|
|
|
re = 7.0;
|
|
|
|
im = 4.0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
It is legal to name the return values in the declaration even if the
|
|
|
|
first form of return statement is used:
|
|
|
|
|
|
|
|
func complex_f2() (re float, im float) {
|
|
|
|
return 7.0, 4.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
If statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
If statements have the traditional form except that the
|
2008-03-06 00:00:44 -07:00
|
|
|
condition need not be parenthesized and the "then" statement
|
2008-03-04 23:18:16 -07:00
|
|
|
must be in brace brackets.
|
|
|
|
|
2008-03-11 17:40:47 -06:00
|
|
|
IfStat = "if" [ SimpleStat ";" ] Expression Block [ "else" Statement ] .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
if x > 0 {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
An if statement may include the declaration of a single temporary variable.
|
|
|
|
The scope of the declared variable extends to the end of the if statement, and
|
|
|
|
the variable is initialized once before the statement is entered.
|
|
|
|
|
|
|
|
if x := f(); x < y {
|
|
|
|
return x;
|
|
|
|
} else if x > z {
|
|
|
|
return z;
|
|
|
|
} else {
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Switch statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Switches provide multi-way execution.
|
|
|
|
|
2008-03-11 17:40:47 -06:00
|
|
|
SwitchStat = "switch" [ [ SimpleStat ";" ] "Expression ] "{" { CaseClause } "}" .
|
2008-03-11 17:02:46 -06:00
|
|
|
CaseClause = CaseList StatementList [ ";" ] [ "fallthrough" [ ";" ] ] .
|
2008-03-06 20:40:52 -07:00
|
|
|
CaseList = Case { Case } .
|
2008-03-11 17:02:46 -06:00
|
|
|
Case = ( "case" ExpressionList | "default" ) ":" .
|
2008-03-06 00:00:44 -07:00
|
|
|
|
|
|
|
There can be at most one default case in a switch statement.
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
The "fallthrough" keyword indicates that the control should flow from
|
2008-03-06 00:00:44 -07:00
|
|
|
the end of this case clause to the first statement of the next clause.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
The expressions do not need to be constants. They will
|
|
|
|
be evaluated top to bottom until the first successful non-default case is reached.
|
|
|
|
If none matches and there is a default case, the statements of the default
|
|
|
|
case are executed.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
switch tag {
|
|
|
|
default: s3()
|
|
|
|
case 0, 1: s1()
|
|
|
|
case 2: s2()
|
|
|
|
}
|
|
|
|
|
|
|
|
A switch statement may include the declaration of a single temporary variable.
|
|
|
|
The scope of the declared variable extends to the end of the switch statement, and
|
|
|
|
the variable is initialized once before the switch is entered.
|
|
|
|
|
|
|
|
switch x := f(); true {
|
|
|
|
case x < 0: return -x
|
|
|
|
default: return x
|
|
|
|
}
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Cases do not fall through unless explicitly marked with a "fallthrough" statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
switch a {
|
|
|
|
case 1:
|
|
|
|
b();
|
2008-03-06 00:00:44 -07:00
|
|
|
fallthrough
|
2008-03-04 23:18:16 -07:00
|
|
|
case 2:
|
|
|
|
c();
|
|
|
|
}
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
If the expression is omitted, it is equivalent to "true".
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
switch {
|
|
|
|
case x < y: f1();
|
|
|
|
case x < z: f2();
|
|
|
|
case x == 4: f3();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-27 22:42:25 -06:00
|
|
|
Select statements
|
|
|
|
----
|
|
|
|
|
|
|
|
A select statement chooses which of a set of possible communications
|
|
|
|
will proceed. It looks similar to a switch statement but with the
|
|
|
|
cases all referring to communication operations.
|
|
|
|
|
|
|
|
SelectStat = "select" "{" { CommClause } "}" .
|
|
|
|
CommClause = CommCase { Statement } .
|
|
|
|
CommCase = ( "default" | ( "case" ( SendCase | RecvCase) ) ) ":" .
|
|
|
|
SendCase = Send .
|
|
|
|
RecvCase = [ identifier '=' ] RecvExpression .
|
|
|
|
RecvExpression = '<' Expression .
|
|
|
|
|
|
|
|
The select statement evaluates all the channel (pointers) involved.
|
|
|
|
If any of the channels can proceed, the corresponding communication
|
|
|
|
and statements are evaluated. Otherwise, if there is a default case,
|
|
|
|
that executes; if not, the statement blocks until one of the
|
|
|
|
communications can complete. A channel pointer may be nil, which is
|
|
|
|
equivalent to that case not being present in the select statement.
|
|
|
|
|
|
|
|
If the channel sends or receives "any" or an interface type, its
|
|
|
|
communication can proceed only if the type of the communication
|
|
|
|
clause matches that of the dynamic value to be exchanged.
|
|
|
|
|
|
|
|
If multiple cases can proceed, a uniform fair choice is made regarding
|
|
|
|
which single communication will execute.
|
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
var c, c1, c2 *chan int;
|
|
|
|
select {
|
|
|
|
case i1 = <c1:
|
|
|
|
printf("received %d from c1\n", i1);
|
|
|
|
case >c2 = i2:
|
|
|
|
printf("sent %d to c2\n", i2);
|
|
|
|
default:
|
|
|
|
printf("no communication\n");
|
|
|
|
}
|
2008-03-27 22:42:25 -06:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
for { // send random sequence of bits to c
|
2008-03-27 22:42:25 -06:00
|
|
|
select {
|
2008-04-18 16:41:59 -06:00
|
|
|
case >c = 0: // note: no statement, no fallthrough, no folding of cases
|
|
|
|
case >c = 1:
|
2008-03-27 22:42:25 -06:00
|
|
|
}
|
2008-04-18 16:41:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
var ca *chan any;
|
|
|
|
var i int;
|
|
|
|
var f float;
|
|
|
|
select {
|
|
|
|
case i = <ca:
|
|
|
|
printf("received int %d from ca\n", i);
|
|
|
|
case f = <ca:
|
|
|
|
printf("received float %f from ca\n", f);
|
|
|
|
}
|
2008-03-27 22:42:25 -06:00
|
|
|
|
|
|
|
TODO: do we allow case i := <c: ?
|
|
|
|
TODO: need to precise about all the details but this is not the right doc for that
|
|
|
|
|
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
For statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
For statements are a combination of the "for" and "while" loops of C.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ForStat = "for" [ Condition | ForClause ] Block .
|
|
|
|
ForClause = [ InitStat ] ";" [ Condition ] ";" [ PostStat ] .
|
2008-03-06 20:40:52 -07:00
|
|
|
|
|
|
|
InitStat = SimpleStat .
|
|
|
|
Condition = Expression .
|
|
|
|
PostStat = SimpleStat .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
A SimpleStat is a simple statement such as an assignment, a SimpleVarDecl,
|
2008-03-06 00:00:44 -07:00
|
|
|
or an increment or decrement statement. Therefore one may declare a loop
|
|
|
|
variable in the init statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
printf("%d\n", i)
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
A for statement with just a condition executes until the condition becomes
|
|
|
|
false. Thus it is the same as C's while statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
for a < b {
|
|
|
|
a *= 2
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
If the condition is absent, it is equivalent to "true".
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 00:00:44 -07:00
|
|
|
for {
|
|
|
|
f()
|
2008-03-04 23:18:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Range statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Range statements are a special control structure for iterating over
|
|
|
|
the contents of arrays and maps.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
RangeStat = "range" IdentifierList ":=" RangeExpression Block .
|
2008-03-06 20:40:52 -07:00
|
|
|
RangeExpression = Expression .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A range expression must evaluate to an array, map or string. The identifier list must contain
|
|
|
|
either one or two identifiers. If the range expression is a map, a single identifier is declared
|
|
|
|
to range over the keys of the map; two identifiers range over the keys and corresponding
|
|
|
|
values. For arrays and strings, the behavior is analogous for integer indices (the keys) and
|
|
|
|
array elements (the values).
|
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
a := []int(1, 2, 3);
|
|
|
|
m := [string]map int("fo",2, "foo",3, "fooo",4)
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
range i := a {
|
|
|
|
f(a[i]);
|
|
|
|
}
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
range v, i := a {
|
|
|
|
f(v);
|
|
|
|
}
|
|
|
|
|
2008-03-04 23:18:16 -07:00
|
|
|
range k, v := m {
|
|
|
|
assert(len(k) == v);
|
|
|
|
}
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
TODO: is this right?
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Break statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Within a for or switch statement, a break statement terminates execution of
|
|
|
|
the innermost for or switch statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
BreakStat = "break" [ identifier ].
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
If there is an identifier, it must be the label name of an enclosing
|
|
|
|
for or switch
|
2008-03-06 00:00:44 -07:00
|
|
|
statement, and that is the one whose execution terminates.
|
|
|
|
|
|
|
|
L: for i < n {
|
|
|
|
switch i {
|
|
|
|
case 5: break L
|
|
|
|
}
|
|
|
|
}
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Continue statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
Within a for loop a continue statement begins the next iteration of the
|
2008-03-06 00:00:44 -07:00
|
|
|
loop at the post statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ContinueStat = "continue" [ identifier ].
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-26 00:53:07 -06:00
|
|
|
The optional identifier is analogous to that of a break statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
Label declaration
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
A label declaration serves as the target of a goto, break or continue statement.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
LabelDecl = identifier ":" .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
Error:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
Goto statements
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
A goto statement transfers control to the corresponding label statement.
|
2008-03-06 00:00:44 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
GotoStat = "goto" identifier .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
goto Error
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-27 18:19:17 -06:00
|
|
|
Executing the goto statement must not cause any variables to come into
|
|
|
|
scope that were not already in scope at the point of the goto. For
|
|
|
|
instance, this example:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-18 16:41:59 -06:00
|
|
|
goto L; // BAD
|
|
|
|
v := 3;
|
|
|
|
L:
|
2008-03-27 18:19:17 -06:00
|
|
|
|
|
|
|
is erroneous because the jump to label L skips the creation of v.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Packages
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
Every source file identifies the package to which it belongs.
|
|
|
|
The file must begin with a package clause.
|
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
PackageClause = "package" PackageName .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
package Math
|
|
|
|
|
|
|
|
|
|
|
|
Import declarations
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
A program can gain access to exported items from another package
|
|
|
|
through an import declaration:
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-11 17:02:46 -06:00
|
|
|
ImportDecl = "import" [ "." | PackageName ] PackageFileName .
|
2008-03-06 20:40:52 -07:00
|
|
|
PackageFileName = string_lit .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
An import statement makes the exported contents of the named
|
|
|
|
package file accessible in this package.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 19:57:03 -07:00
|
|
|
In the following discussion, assume we have a package in the
|
|
|
|
file "/lib/math", called package Math, which exports functions sin
|
|
|
|
and cos.
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
import M "/lib/math"
|
|
|
|
|
|
|
|
the contents of the package /lib/math can be accessed by
|
|
|
|
M.cos, M.sin, etc.
|
|
|
|
|
|
|
|
In its simplest form, with no package name, the import statement
|
|
|
|
implicitly uses the imported package name itself as the local
|
|
|
|
package name. After
|
|
|
|
|
|
|
|
import "/lib/math"
|
|
|
|
|
|
|
|
the contents are accessible by Math.sin, Math.cos.
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
import . "/lib/math"
|
|
|
|
|
|
|
|
the contents are accessible by sin and cos. In this instance, it is
|
|
|
|
an error if the import introduces name conflicts.
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
Program
|
2008-03-06 20:40:52 -07:00
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
|
|
|
A program is package clause, optionally followed by import declarations,
|
|
|
|
followed by a series of declarations.
|
|
|
|
|
2008-03-11 21:40:20 -06:00
|
|
|
Program = PackageClause { ImportDecl } { Declaration } .
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-04-29 17:27:11 -06:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
TODO
|
|
|
|
----
|
2008-03-04 23:18:16 -07:00
|
|
|
|
2008-03-06 20:40:52 -07:00
|
|
|
- TODO: type switch?
|
|
|
|
- TODO: words about slices
|
2008-04-18 16:41:59 -06:00
|
|
|
- TODO: I (gri) would like to say that sizeof(int) == sizeof(pointer), always.
|
2008-04-27 19:32:47 -06:00
|
|
|
- TODO: when are two types equal? consider
|
|
|
|
func iterate(f *func(int, interface{}), arg interface{})
|