diff --git a/doc/go_lang.txt b/doc/go_lang.txt index 96b5561641..79d01658dd 100644 --- a/doc/go_lang.txt +++ b/doc/go_lang.txt @@ -17,8 +17,8 @@ The design is motivated by the following guidelines: - strongly typed - concise syntax avoiding repetition - few, orthogonal, and general concepts -- excellent support for threading and interprocess communication -- efficient garbage collection +- support for threading and interprocess communication +- garbage collection - container library written in Go - reasonably efficient (C ballpark) @@ -34,12 +34,11 @@ individual identifiers visible to other files by marking them as exported; there is no "header file". A package collects types, constants, functions, and so on into a named -entity that may be imported to enable its constituents be used in +entity that may be exported to enable its constituents be used in another compilation unit. Because there are no header files, all identifiers in a package are either -declared explicitly within the package or, in certain cases, arise from an -import statement. +declared explicitly within the package or arise from an import statement. Scoping is essentially the same as in C. @@ -64,20 +63,9 @@ still under development. Typing, polymorphism, and object-orientation -Go programs are strongly typed: each program entity has a static -type known at compile time. Variables also have a dynamic type, which -is the type of the value they hold at run-time. Usually, the -dynamic and the static type of a variable are identical, except for -variables of interface type. In that case the dynamic type of the -variable is a pointer to a structure that implements the variable's -(static) interface type. There may be many different structures -implementing an interface and thus the dynamic type of such variables -is generally not known at compile time. Such variables are called -polymorphic. - -Also, certain expressions, in particular map and channel accesses, -can also be polymorphic. The language provides mechanisms to -make use of such polymorphic values type-safe. +Go programs are strongly typed. Certain expressions, in particular map +and channel accesses, can also be polymorphic. The language provides +mechanisms to make use of such polymorphic values type-safe. Interface types are the mechanism to support an object-oriented programming style. Different interface types are independent of each @@ -130,7 +118,8 @@ language support. Values and references -Unless accessing expliciting through a pointer, all objects are values. +All objects have value semantics, but its contents may be accessed +through different pointers referring to the same object. 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 @@ -151,9 +140,9 @@ Here is a complete example Go program that implements a concurrent prime sieve: ============================ package Main -// Send the sequence 2, 3, 4, ... to channel 'c'. -func Generate(ch *chan< int) { - for i := 2; true; i++ { +// Send the sequence 2, 3, 4, ... to channel 'ch'. +func Generate(ch *chan> int) { + for i := 2; ; i++ { >ch = i; // Send 'i' to channel 'ch'. } } @@ -161,7 +150,7 @@ func Generate(ch *chan< int) { // Copy the values from channel 'in' to channel 'out', // removing those divisible by 'prime'. func Filter(in *chan< int, out *chan> int, prime int) { - while true { + for ; ; { i := out = i; // Send 'i' to channel 'out'. @@ -173,7 +162,7 @@ func Filter(in *chan< int, out *chan> int, prime int) { func Sieve() { ch := new(chan int); // Create a new channel. go Generate(ch); // Start Generate() as a subprocess. - while true { + for ; ; { prime := ' ] [ Type ] . +ChannelType = 'chan' [ '<' | '>' ] ValueType . - chan // a generic channel + 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< // a channel that can receive (only) values of any type + chan< any // a channel that can receive (only) values of any type Channel variables always have type pointer to channel. It is an error to attempt to dereference a channel pointer. @@ -682,6 +677,8 @@ Block = '{' [ StatementList ] '}' . A function literal can be invoked or assigned to a variable of the corresponding function pointer type. +For now, a function literal can reference only its parameters, global +variables, and variables declared within the function literal. // Function literal func (a, b int, z float) bool { return a*b < int(z); } @@ -700,10 +697,13 @@ a method indicates the type of the struct by declaring a receiver of type the declaration - func (p *Point) distance(float scale) float { return scale * (p.x*p.x + p.y*p.y) } + func (p *Point) distance(float scale) float { + return scale * (p.x*p.x + p.y*p.y); + } creates a method of type Point. Note that methods are not declared -within their struct type declaration. They may appear anywhere. +within their struct type declaration. They may appear anywhere and +may be forward-declared for commentary. 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 @@ -736,9 +736,9 @@ MethodDecl = identifier Parameters [ Result ] ';' . Close(); } -Any struct that has, as a subset, the methods of that interface is -said to implement the interface. For instance, if two struct types -S1 and S2 have the methods +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 func (p *T) Read(b Buffer) bool { return ... } func (p *T) Write(b Buffer) bool { return ... } @@ -860,7 +860,8 @@ Function and method declarations Functions and methods have a special declaration syntax, slightly different from the type syntax because an identifier must be present -in the signature. +in the signature. For now, functions and methods can only be declared +at the global level. FunctionDecl = 'func' NamedSignature ( ';' | Block ) . NamedSignature = [ Receiver ] identifier Parameters [ Result ] . @@ -900,7 +901,7 @@ Functions and methods can be forward declared by omitting the body: Export declarations -Globally declared identifiers may be exported, thus making the +Global identifiers may be exported, thus making the exported identifer visible outside the package. Another package may then import the identifier to use it. @@ -966,10 +967,11 @@ can be simplified to Expression = Conjunction { '||' Conjunction }. Conjunction = Comparison { '&&' Comparison }. Comparison = SimpleExpr [ relation SimpleExpr ]. -relation = '==' | '!=' | '<' | '<=' | '>' | '>='. SimpleExpr = Term { add_op Term }. -add_op = '+' | '-' | '|' | '^'. Term = Operand { mul_op Operand }. + +relation = '==' | '!=' | '<' | '<=' | '>' | '>='. +add_op = '+' | '-' | '|' | '^'. mul_op = '*' | '/' | '%' | '<<' | '>>' | '&'. The corresponding precedence hierarchy is as follows: @@ -996,13 +998,14 @@ and (a / b) is "truncated towards zero". The shift operators implement arithmetic shifts for signed integers, -and logical shifts for unsigned integers. +and logical shifts for unsigned integers. The property of negative +shift counts are undefined. There are no implicit type conversions except for constants and literals. In particular, unsigned and signed integers cannot be mixed in an expression w/o explicit casting. -Unary '^' corresponds to C '~' (bitwise negate). +Unary '^' corresponds to C '~' (bitwise complement). Statements @@ -1016,7 +1019,7 @@ Statement = GoStat | ReturnStat | IfStat | SwitchStat | - WhileStat | ForStat | RangeStat | + ForStat | RangeStat | BreakStat | ContinueStat | GotoStat | LabelStat . @@ -1066,22 +1069,39 @@ or an array indexing. A tuple assignment assigns the individual elements of a multi-valued operation, such function evaluation or some channel and map operations, into individual -variables. Tuple assignment is simultaneous. -For example, +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 a, b = b, a -exchanges the values of a and b. +exchanges the values of a and b. The tuple assignment x, y = f() + +calls the function f, which must return 2 values and assigns them to x and y. +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. + value, present = map_var[key] + +Analogously, receiving a value from a channel can be written as a tuple assignment. + value, success = chan_ptr = value - + In assignments, the type of the expression must match the type of the designator. @@ -1136,13 +1156,11 @@ first form of return statement is used: If statements -[ NOTE We propose a simplified control syntax ] - If statements have the traditional form except that the -condition need not be parenthesized and the statements +condition need not be parenthesized and the "then" statement must be in brace brackets. -IfStat = 'if' [ SimpleVarDecl ';' ] Expression Block [ 'else' ( Block | IfStat ) ] . +IfStat = 'if' [ SimpleVarDecl ';' ] Expression Block [ 'else' Statement ] . if x > 0 { return true; @@ -1165,13 +1183,20 @@ Switch statements Switches provide multi-way execution. -SwitchStat = 'switch' [ SimpleVarDecl ';' ] [ Expression ] '{' CaseList '}' . -CaseList = ( 'case' ExpressionList | 'default' ) ':' { Statement | 'fallthrough' ';' } . +SwitchStat = 'switch' [ [ SimpleVarDecl ';' ] [ Expression ] ] '{' { CaseClause } '}' . +CaseClause = CaseList { Statement } [ 'fallthrough' ] . +CaseList = Case { Case } . +Case = ( 'case' ExpressionList | 'default' ) ':' . -Note that the expressions do not need to be constants. They will -be evaluated top to bottom until the first successful non-defauit case. -If none matches and there is a default case, the default case is -executed. +There can be at most one default case in a switch statement. + +The 'fallthrough' keyword indicates that the control should flow from +the end of this case clause to the first statement of the next clause. + +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. switch tag { default: s3() @@ -1187,13 +1212,13 @@ the variable is initialized once before the switch is entered. case x < 0: return -x default: return x } - + Cases do not fall through unless explicitly marked with a 'fallthrough' statement. switch a { case 1: b(); - fallthrough; + fallthrough case 2: c(); } @@ -1207,43 +1232,36 @@ If the expression is omitted, it is equivalent to 'true'. } -While statements - -A while statement is the usual loop construct. - -WhileStat = 'while' [ SimpleVarDecl ';' ] Expression Block . - - while a < b { - a++ - } - -A while statement may include the declaration of a single temporary variable. -The scope of the declared variable extends to the end of the while statement, and -the variable is initialized once before the loop is entered. - - while x :=