From: Robert Griesemer Date: Wed, 5 Mar 2008 06:18:16 +0000 (-0800) Subject: - added new, revised spec X-Git-Tag: weekly.2009-11-06~3844 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=73823d236a063e9e1fd326c07797be3a08b79edb;p=gostls13.git - added new, revised spec - updated todo SVN=111357 --- diff --git a/doc/go_lang.txt b/doc/go_lang.txt new file mode 100644 index 0000000000..96b5561641 --- /dev/null +++ b/doc/go_lang.txt @@ -0,0 +1,1347 @@ +The Go Programming Language + +This document is an informal specification/proposal for a new systems programming +language. + + +Guiding principles + +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 +- excellent support for threading and interprocess communication +- efficient garbage collection +- 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 + +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 +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 +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. + +Scoping is essentially the same as in C. + + +Program structure + +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 +package, by default called Main, is the starting point for execution. +It contains a function, also called Main, that is the first function invoked +by the run time system. + +If any package within the program +contains a function Init(), that function will be executed +before Main.Main() is called. The details of initialization are +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. + +Interface types are the mechanism to support an object-oriented +programming style. Different interface types are independent of each +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 +can always be statically bound (they are not "virtual"), and incur no +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 +use of abstract data types operating on interface types. + + +Pointers and garbage collection + +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 + +Functions contain declarations and statements. They may be +recursive. Functions may be anonymous and appear as +literals in expressions. + + +Multithreading and channels + +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 + +Unless accessing expliciting through a pointer, all objects are values. +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 +byte strings. + + +Syntax + +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: + +============================ +package Main + +// Send the sequence 2, 3, 4, ... to channel 'c'. +func Generate(ch *chan< int) { + for i := 2; true; i++ { + >ch = i; // Send 'i' to channel 'ch'. + } +} + +// 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 { + i := out = i; // Send 'i' to channel 'out'. + } + } +} + +// 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. + while true { + prime := ' ] [ Type ] . + + chan // 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 + +Channel variables always have type pointer to channel. +It is an error to attempt to dereference a channel pointer. + +There are no channel literals. + + +Function types + +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. + +FunctionType = 'func' AnonymousSignature . +AnonymousSignature = [ Receiver '.' ] Parameters [ Result ] . +Receiver = '(' identifier Type ')' . +Parameters = '(' [ ParameterList ] ')' . +ParameterList = ParameterSection { ',' ParameterSection } . +ParameterSection = [ IdentifierList ] Type . +Result = [ Type ] | '(' ParameterList ')' . + + // 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) + + // 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) + +A variable can only hold a pointer to a function, but 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. + + +Function Literals + +Function literals represent anonymous functions. + +FunctionLit = FunctionType Block . +Block = '{' [ StatementList ] '}' . + +A function literal can be invoked +or assigned to a variable of the corresponding function pointer type. + + // Function literal + func (a, b int, z float) bool { return a*b < int(z); } + + // Method literal + func (p *T) . (a, b int, z float) bool { return a*b < int(z) + p.x; } + + +Methods + +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 + + 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. + +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 + +The interface of a struct is defined to be the unordered set of methods +associated with that struct. + + +Interface types + +An interface type denotes a set of methods. + +InterfaceType = 'interface' '{' { MethodDecl } '}' . +MethodDecl = identifier Parameters [ Result ] ';' . + + // A basic file interface. + type File interface { + Read(b Buffer) bool; + Write(b Buffer) bool; + 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 + + 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. + +There are no interface literals. + + +Literals + +Literal = BasicLit | CompoundLit . +BasicLit = CharLit | StringLit | IntLit | FloatLit . +CompoundLit = ArrayLit | MapLit | StructLit | FunctionLit . + + +Declarations + +A declaration associates a name with a language entity such as a type, +constant, variable, or function. + +Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | ExportDecl . + + +Const declarations + +A constant declaration gives a name to the value of a constant expression. + +ConstDecl = 'const' ( ConstSpec | '(' ConstSpecList [ ';' ] ')' ). +ConstSpec = identifier [ Type ] '=' Expression . +ConstSpecList = ConstSpec { ';' ConstSpec }. + + const pi float = 3.14159265 + const e = 2.718281828 + const ( + one int = 1; + two = 3 + ) + + +Type declarations + +A type declaration introduces a name as a shorthand for a type. +In certain situations, such as conversions, it may be necessary to +use such a type name. + +TypeDecl = 'type' ( TypeSpec | '(' TypeSpecList [ ';' ] ')' ). +TypeSpec = identifier Type . +TypeSpecList = TypeSpec { ';' TypeSpec }. + + + type IntArray [16] int + type ( + Point struct { x, y float }; + Polar Point + ) + + +Variable declarations + +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. + +VarDecl = 'var' ( VarSpec | '(' VarSpecList [ ';' ] ')' ) | SimpleVarDecl . +VarSpec = IdentifierList ( Type [ '=' ExpressionList ] | '=' ExpressionList ) . +VarSpecList = VarSpec { ';' VarSpec } . + + 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 + + SimpleVarDecl = identifier ':=' Expression . + +is syntactic shorthand for + + var identifer = Expression. + + i := 0 + f := func() int { return 7; } + ch := new(chan int); + +Also, in some contexts such as if or while statements, this construct can be used to +declare local temporary variables. + + +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. + +FunctionDecl = 'func' NamedSignature ( ';' | Block ) . +NamedSignature = [ Receiver ] identifier Parameters [ Result ] . + + func min(x int, y int) int { + if x < y { + return x; + } + return y; + } + + func foo (a, b int, z float) bool { + return a*b < int(z); + } + + +A method is a function that also declares a receiver. + + func (p *T) foo (a, b int, z float) bool { + 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: + + func foo (a, b int, z float) bool; + func (p *T) foo (a, b int, z float) bool; + + +Export declarations + +Globally declared identifiers may be exported, thus making the +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 +compilation unit. That is, one can export +compilation-unit global identifiers but not, for example, local +variables or structure fields. + +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. + +ExportDecl = 'export' ExportIdentifier { ',' ExportIdentifier } . +ExportIdentifier = QualifiedIdent . + +export sin, cos +export Math.abs + +[ TODO complete this section ] + + +Expressions + +Expression syntax is based on that of C. + +Operand = Literal | Designator | UnaryExpr | '(' Expression ')' | Call. +UnaryExpr = unary_op Expression +unary_op = '!' | '-' | '^' | '&' | '<' . +Designator = QualifiedIdent { Selector }. +Selector = '.' identifier | '[' Expression [ ':' Expression ] ']'. +Call = Operand '(' ExpressionList ')'. + + 2 + a[i] + "hello" + f("abc") + p.q.r + a.m(zot, bar) + ' | '>='. +SimpleExpr = Term { add_op Term }. +add_op = '+' | '-' | '|' | '^'. +Term = Operand { mul_op Operand }. +mul_op = '*' | '/' | '%' | '<<' | '>>' | '&'. + +The corresponding precedence hierarchy is as follows: + +Precedence Operator + 1 || + 2 && + 3 == != < <= > >= + 4 + - | ^ + 5 * / % << >> & + + 23 + 3*x[i] + x <= f() + a >> ~b + f() || g() + x == y || 0 + +For integer values, / and % satisfy the following relationship: + + (a / b) * b + a % b == a + +and + + (a / b) is "truncated towards zero". + +The shift operators implement arithmetic shifts for signed integers, +and logical shifts for unsigned integers. + +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). + + +Statements + +Statements control execution. + +Statement = + Declaration | + ExpressionStat | IncDecStat | CompoundStat | + Assignment | + GoStat | + ReturnStat | + IfStat | SwitchStat | + WhileStat | ForStat | RangeStat | + BreakStat | ContinueStat | GotoStat | LabelStat . + + +Expression statements + +ExpressionStat = Expression . + + f(x+y) + + +IncDec statements + +IncDecStat = Expression ( '++' | '--' ) . + + a[i]++ + +Note that ++ and -- are not operators for expressions. + + +Compound statements + +CompoundStat = '{' { Statement } '}' . + + { + x := 1; + f(x); + } + +The scope of an Identifier declared within a compound statement extends +from the declaration to the end of the compound statement. + + +Assignments + +Assignment = SingleAssignment | TupleAssignment | Send . +SimpleAssignment = Designator '=' Expression . +TupleAssignment = DesignatorList '=' ExpressionList . +Send = '>' Expression = Expression . + +The designator must be an l-value such as a variable, pointer indirection, +or an array indexing. + + x = 1 + *p = f() + a[i] = 23 + + +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, + + a, b = b, a + +exchanges the values of a and b. + + x, y = f() + value, present = map_var[key] + value, success = chan_ptr = value + +In assignments, the type of the expression must match the type of the designator. + + +Go statements + +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. + +GoStat = 'go' Call . + + go Server() + go func(ch chan> bool) { for ;; { sleep(10); >ch = true; }} (c) + + +Return statements + +A return statement terminates execution of the containing function +and optionally provides a result value or values to the caller. + +ReturnStat = 'return' [ ExpressionList ] . + +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: + + func simple_f () int { + return 2; + } + + func complex_f1() (re float, im float) { + 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 + +[ NOTE We propose a simplified control syntax ] + +If statements have the traditional form except that the +condition need not be parenthesized and the statements +must be in brace brackets. + +IfStat = 'if' [ SimpleVarDecl ';' ] Expression Block [ 'else' ( Block | IfStat ) ] . + + 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 + +Switches provide multi-way execution. + +SwitchStat = 'switch' [ SimpleVarDecl ';' ] [ Expression ] '{' CaseList '}' . +CaseList = ( 'case' ExpressionList | 'default' ) ':' { Statement | 'fallthrough' ';' } . + +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. + + 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 + } + +Cases do not fall through unless explicitly marked with a 'fallthrough' statement. + + switch a { + case 1: + b(); + fallthrough; + case 2: + c(); + } + +If the expression is omitted, it is equivalent to 'true'. + + switch { + case x < y: f1(); + case x < z: f2(); + case x == 4: f3(); + } + + +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 :=