[インデックス 1721] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
ファイルに対する大幅な改訂です。このファイルは、Go言語の構文、セマンティクス、組み込み関数、パッケージの動作など、言語のあらゆる側面を詳細に記述した中心的なドキュメントです。このコミットは、特にステートメント(文)、型変換、メモリ割り当て、パッケージの初期化に関する記述を明確化し、詳細化することを目的としています。
コミット
commit 96750f130c64cf90777962cb6d7701a9faaee9f6
Author: Rob Pike <r@golang.org>
Date: Fri Feb 27 16:47:48 2009 -0800
most of the rest.
only the package section is untouched.
R=gri
DELTA=542 (186 added, 70 deleted, 286 changed)
OCL=25485
CL=25532
---
doc/go_spec.html | 688 ++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 402 insertions(+), 286 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 64de93adc6..d49df958c1 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -2278,17 +2278,18 @@ returning a value and a boolean indicating success. (§Assignments)
<h3>Calls</h3>
<p>
-Given a function or a function variable <code>f</code> of function type
-<code>F</code>, the expression
+Given an expression <code>f</code> of function type
+<code>F</code>,
</p>
<pre>
-f(a, b, c)
+f(a1, a2, ... an)
</pre>
<p>
-calls the function with arguments <code>a, b, c</code>.
-The arguments must be assignment compatible with the parameters of
+calls <code>f</code> with arguments <code>a1, a2, ... an</code>.
+The arguments must be single-valued expressions
+assignment compatible with the parameters of
<code>F</code> and are evaluated before the function is called.\n The type of the expression is the result type
of <code>F</code>.\n@@ -2859,76 +2860,98 @@ but not <code>uint64</code> or <code>string</code>.\n \n <h2>Statements</h2>\n \n+<p>\n Statements control execution.\n+</p>\n \n <pre class=\"grammar\">\n-Statement =\n-\tDeclaration | LabelDecl | EmptyStat |\n+Statement = { Label \":\" } UnlabeledStatement .\n+Label = identifier .\n+UnlabeledStatement =\n+\tDeclaration | EmptyStat |\n \tSimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |\n \tFallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat |\n \tDeferStat .\n \n SimpleStat =\n \tExpressionStat | IncDecStat | Assignment | SimpleVarDecl .\n-</pre>\n-\n \n-Statements in a statement list are separated by semicolons, which can be\n-omitted in some cases as expressed by the OptSemicolon production.\n-\n-<pre class=\"grammar\">\n-StatementList = Statement { OptSemicolon Statement } .\n+StatementList = Statement { Separator Statement } .\n+Separator = [ \";\" ]\n </pre>\n \n <p>\n-A semicolon may be omitted immediately following:\n+Elements of a list of statements are separated by semicolons,\n+which may be omitted only if the previous statement:\n </p>\n <ul>\n-\t<li>a closing parenthesis \")\" ending a list of declarations (§Declarations and Scope)\n-\t<li>a closing brace \"}\" ending a type declaration (§Type declarations)\n-\t<li>a closing brace \"}\" ending a block (including switch and select statements)\n-\t<li>a label declaration (§Label declarations)\n+\t<li>ends with the closing parenthesis \")\" of a list of declarations\n+\t (§Declarations and Scope); or</li>\n+\t<li>ends with the closing brace \"}\" of a type declaration\n+\t (§Type declarations); or </li>\n+\t<li>ends with the closing brace \"}\" of a block\n+\t (including \"switch\" and \"select\" statements).\n </ul>\n \n-In all other cases a semicolon is required to separate two statements. Since there\n-is an empty statement, a statement list can always be ``terminated\'\' with a semicolon.\n+<p>\n+A labeled statement may be the target of a <code>goto</code>, \n+<code>break</code> or <code>continue</code> statement.\n+</p>\n \n+<pre>\n+Error: log.Fatal(\"error encountered\")\n+</pre>\n \n <h3>Empty statements</h3>\n \n+<p>\n The empty statement does nothing.\n+</p>\n \n <pre class=\"grammar\">\n EmptyStat = .\n </pre>\n \n+<p>\n+A statement list can always in effect be terminated with a semicolon by\n+adding an empty statement.\n+</p>\n+\n \n <h3>Expression statements</h3>\n \n+<p>\n+Function calls, method calls, and channel operations\n+can appear in statement context.\n+</p>\n+\n+\n <pre class=\"grammar\">\n ExpressionStat = Expression .\n </pre>\n \n <pre>\n f(x+y)\n+<-ch\n </pre>\n \n-<font color=red>\n-TODO: specify restrictions. 6g only appears to allow calls here.\n-</font>\n-\n \n <h3>IncDec statements</h3>\n \n+<p>\n The \"++\" and \"--\" statements increment or decrement their operands\n-by the (ideal) constant value 1.\n+by the ideal numeric value 1. As with an assignment, the operand\n+must be a variable, pointer indirection, field selector or index expression.\n+</p>\n \n <pre class=\"grammar\">\n IncDecStat = Expression ( \"++\" | \"--\" ) .\n </pre>\n \t\n+<p>\n The following assignment statements (§Assignments) are semantically\n equivalent:\n+</p>\n \n <pre class=\"grammar\">\n IncDec statement Assignment\n@@ -2936,12 +2959,6 @@ x++ x += 1\n x-- x -= 1\n </pre>\n \n-Both operators apply to integer and floating point types only.\n-<p>\n-Note that increment and decrement are statements, not expressions.\n-For instance, \"x++\" cannot be used as an operand in an expression.\n-\n-\n <h3>Assignments</h3>\n \n <pre class=\"grammar\">\n@@ -2950,8 +2967,10 @@ Assignment = ExpressionList assign_op ExpressionList .\n assign_op = [ add_op | mul_op ] \"=\" .\n </pre>\n \n-The left-hand side must be an l-value such as a variable, pointer indirection,\n-or an array index.\n+<p>\n+Each left-hand side operand must be a variable, pointer indirection,\n+field selector, or index expression.\n+</p>\n \n <pre>\n x = 1\n@@ -2959,64 +2978,67 @@ x = 1\n a[i] = 23\n k = <-ch\n </pre>\n-\t\n-As in C, arithmetic binary operators can be combined with assignments:\n \n-<pre>\n-j <<= 2\n-</pre>\n-\n-A tuple assignment assigns the individual elements of a multi-valued operation,\n-such as function evaluation or some channel and map operations, into individual\n-variables. For instance, a tuple assignment such as\n-\n-<pre>\n-v1, v2, v3 = e1, e2, e3\n-</pre>\n-\t\n-assigns the expressions e1, e2, e3 to temporaries and then assigns the temporaries\n-to the variables v1, v2, v3. Thus\n+<p>\n+An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>\n+<code>y</code> where <i>op</i> is a binary arithmetic operation is equivalent\n+to <code>x</code> <code>=</code> <code>x</code> <i>op</i>\n+<code>y</code> but evalutates <code>x</code>\n+only once. The <i>op</i><code>=</code> construct is a single token.\n+</p>\n \n <pre>\n-a, b = b, a\n+a[i] <<= 2\n </pre>\n \n-exchanges the values of a and b. The tuple assignment\n+<p>\n+A tuple assignment assigns the individual elements of a multi-valued\n+operation to a list of variables. There are two forms. In the\n+first, the right hand operand is a single multi-valued expression\n+such as a function evaluation or channel or map operation (§Channel\n+operations, §Map operations). The number of operands on the left\n+hand side must match the number of values. For instance, If\n+<code>f</code> is a function returning two values,\n+</p>\n \n <pre>\n x, y = f()\n </pre>\n \n-calls the function f, which must return two values, and assigns them to x and y.\n-As a special case, retrieving a value from a map, when written as a two-element\n-tuple assignment, assign a value and a boolean. If the value is present in the map,\n-the value is assigned and the second, boolean variable is set to true. Otherwise,\n-the variable is unchanged, and the boolean value is set to false.\n-\t\n-<pre>\n-value, present = map_var[key]\n-</pre>\n+<p>\n+assigns the first value to <code>x</code> and the second to <code>y</code>.\n+</p>\n \n-To delete a value from a map, use a tuple assignment with the map on the left\n-and a false boolean expression as the second expression on the right, such\n-as:\n+<p>\n+In the second form, the number of operands on the left must equal the number\n+of expressions on the right, each of which must be single-valued. The\n+expressions are assigned to temporaries and then the temporaries\n+are assigned to the variables.\n+</p>\n \n <pre>\n-map_var[key] = value, false\n+a, b = b, a // exchange a and b\n </pre>\n-\t\t\n-In assignments, the type of the expression must match the type of the left-hand side.\n+\n+<p>\n+In assignments, the type of each value must be assignment compatible\n+(§Assignment compatibility) with the type of the\n+operand to which it is assigned.\n+</p>\n \n \n <h3>If statements</h3>\n \n-If statements specify the conditional execution of two branches; the \"if\"\n-and the \"else\" branch. If Expression evaluates to true,\n-the \"if\" branch is executed. Otherwise the \"else\" branch is executed if present.\n-If Condition is omitted, it is equivalent to true.\n+<p>\n+\"If\" statements specify the conditional execution of two branches\n+according to the value of a boolean expression. If the expression\n+evaluates to true, the \"if\" branch is executed, otherwise, if\n+present, the \"else\" branch is executed. A missing condition\n+is equivalent to <code>true</code>.\n+</p>\n \n <pre class=\"grammar\">\n-IfStat = \"if\" [ [ SimpleStat ] \";\" ] [ Expression ] Block [ \"else\" Statement ] .\n+IfStat = \"if\" [ [ SimpleStat ] \";\" ] [ Expression ] Block [ \"else\" Statement ] .\n </pre>\n \n <pre>\n@@ -3025,9 +3047,12 @@ if x > 0 {\n }\n </pre>\n \n-An \"if\" statement may include the declaration of a single temporary variable.\n-The scope of the declared variable extends to the end of the if statement, and\n-the variable is initialized once before the statement is entered.\n+<code>\n+An \"if\" statement may include a short variable declaration before the expression\n+(§Short variable declarations).\n+The scope of the declared variables extends to the end of the \"if\" statement\n+and the variables are initialized once before the statement is entered.\n+</code>\n \n <pre>\n if x := f(); x < y {\n@@ -3063,83 +3088,86 @@ without the surrounding Block:\n \n <h3>Switch statements</h3>\n \n-Switches provide multi-way execution.\n+<p>\n+\"Switch\" statements provide multi-way execution.\n+An expression is evaluated and compared to the \"case\"\n+expressions inside the \"switch\" to determine which branch\n+of the \"switch\" to execute.\n+A missing expression is equivalent to <code>true</code>.\n+</p>\n \n <pre class=\"grammar\">\n-SwitchStat = \"switch\" [ [ SimpleStat ] \";\" ] [ Expression ] \"{\" { CaseClause } \"}\" .\n-CaseClause = SwitchCase \":\" [ StatementList ] .\n-SwitchCase = \"case\" ExpressionList | \"default\" .\n+SwitchStat = \"switch\" [ [ SimpleStat ] \";\" ] [ Expression ] \"{\" { CaseClause } \"}\" .\n+CaseClause = SwitchCase \":\" [ StatementList ] .\n+SwitchCase = \"case\" ExpressionList | \"default\" .\n </pre>\n \n-There can be at most one default case in a switch statement. In a case clause,\n-the last statement only may be a fallthrough statement ($Fallthrough statement).\n-It indicates that the control should flow from the end of this case clause to\n+<p>\n+The case expressions, which need not be constants,\n+are evaluated top-to-bottom; the first one that matches\n+triggers execution of the statements of the associated case;\n+the other cases are skipped.\n+If no case matches and there is a \"default\" case, its statements are executed.\n+There can be at most one default case and it may appear anywhere in the\n+\"switch\" statement.\n+</p>\n+<p>\n+In a case or default clause,\n+the last statement only may be a \"fallthrough\" statement\n+($Fallthrough statement) to\n+indicate that control should flow from the end of this clause to\n the first statement of the next clause.\n+Otherwise control flows to the end of the \"switch\" statement.\n+</p>\n <p>\n Each case clause effectively acts as a block for scoping purposes\n ($Declarations and scope rules).\n+</p>\n <p>\n-The expressions do not need to be constants. They will\n-be evaluated top to bottom until the first successful non-default case is reached.\n-If none matches and there is a default case, the statements of the default\n-case are executed.\n+A \"switch\" statement may include a short variable declaration before the\n+expression.\n+The scope of the declared variables extends to the end of the \"switch\" statement\n+and the variables are initialized once before the statement is entered. \n+</p>\n \n <pre>\n switch tag {\n-default: s3()\n-case 0, 1: s1()\n-case 2: s2()\n-}\n-</pre>\n-\n-A switch statement may include the declaration of a single temporary variable.\n-The scope of the declared variable extends to the end of the switch statement, and\n-the variable is initialized once before the switch is entered. \n-\n-<pre>\n-switch x := f(); true {\n-case x < 0: return -x\n-default: return x\n+ default: s3()\n+ case 0, 1, 2, 3: s1()\n+ case 4, 5, 6, 7: s2()\n }\n-</pre>\n-\t\n-Cases do not fall through unless explicitly marked with a \"fallthrough\" statement.\n \n-<pre>\n-switch a {\n-case 1:\n-\tb();\n-\tfallthrough\n-case 2:\n-\tc();\n+switch x := f(); {\n+ case x < 0: return -x\n+ default: return x\n }\n-</pre>\n-\n-If the expression is omitted, it is equivalent to \"true\".\n \n-<pre>\n-switch {\n-case x < y: f1();\n-case x < z: f2();\n-case x == 4: f3();\n+switch { // missing expression means \"true\"\n+ case x < y: f1();\n+ case x < z: f2();\n+ case x == 4: f3();\n }\n </pre>\n \n \n <h3>For statements</h3>\n \n-A for statement specifies repeated execution of a block. The iteration is\n-controlled by a condition, a for clause, or a range clause.\n+<p>\n+A \"for\" statement specifies repeated execution of a block. The iteration is\n+controlled by a condition, a \"for\" clause, or a \"range\" clause.\n+</p>\n \n <pre class=\"grammar\">\n ForStat = \"for\" [ Condition | ForClause | RangeClause ] Block .\n Condition = Expression .\n </pre>\n \n-In its simplest form, a for statement specifies the repeated execution of\n-a block as long as a condition evaluates to true. The condition is evaluated\n-before each iteration. The type of the condition expression must be boolean.\n-If the condition is absent, it is equivalent to \"true\".\n+<p>\n+In its simplest form, a \"for\" statement specifies the repeated execution of\n+a block as long as a boolean condition evaluates to true.\n+The condition is evaluated before each iteration.\n+If the condition is absent, it is equivalent to <code>true</code>.\n+</p>\n \n <pre>\n for a < b {\n@@ -3147,10 +3175,15 @@ for a < b {\n }\n </pre>\n \n-A for statement with a for clause is also controlled by its condition, but\n-additionally it may specify an init and post statement, such as an assignment,\n-an increment or decrement statement. The init statement may also be a (simple)\n-variable declaration; no variables can be declared in the post statement.\n+<p>\n+A \"for\" statement with a \"for\" clause is also controlled by its condition, but\n+additionally it may specify an <i>init</i>\n+and a <i>post</i> statement, such as an assignment,\n+an increment or decrement statement. The init statement (but not the post\n+statement) may also be a short variable declaration; the scope of the variables\n+it declares ends at the end of the statement\n+($Declarations and scope rules).\n+</p>\n \n <pre class=\"grammar\">\n ForClause = [ InitStat ] \";\" [ Condition ] \";\" [ PostStat ] .\n@@ -3158,55 +3191,60 @@ InitStat = SimpleStat .\n PostStat = SimpleStat .\n </pre>\n \n-For instance, one may declare an iteration variable in the init statement:\n-\n <pre>\n for i := 0; i < 10; i++ {\n \tf(i)\n }\n </pre>\n \t\n-If present, the init statement is executed once before commencing the iteration;\n-the post statement is executed after each execution of the statement block (and\n-only if the block was executed). The scope of any variable declared in the init\n-statement ends with the end of the for statement block ($Declarations and scope\n-rules, Rule 3).\n <p>\n-The init and post statement as well as the condition may be omitted; however\n-if either the init or post statement are present, the separating semicolons\n-must be present. If the condition is absent, it is equivalent to \"true\".\n-The following statements are equivalent:\n+If non-empty, the init statement is executed once before evaluating the\n+condition for the first iteration;\n+the post statement is executed after each execution of the block (and\n+only if the block was executed).\n+Any element of the \"for\" clause may be empty but the semicolons are\n+required unless there is only a condition.\n+If the condition is absent, it is equivalent to <code>true</code>.\n+</p>\n \n <pre>\n for ; cond ; { S() } is the same as for cond { S() }\n for true { S() } is the same as for { S() }\n </pre>\n \n-Alternatively, a for statement may be controlled by a range clause. A\n-range clause specifies iteration through all entries of an array or map.\n+<p>\n+A \"for\" statement with a \"range\" clause\n+iterates through all entries of an array, slice or map.\n For each entry it first assigns the current index or key to an iteration\n variable - or the current (index, element) or (key, value) pair to a pair\n-of iteration variables - and then executes the block. Iteration terminates\n-when all entries have been processed, or if the for statement is terminated\n-early, for instance by a break or return statement.\n+of iteration variables - and then executes the block.\n+</p>\n \n <pre class=\"grammar\">\n RangeClause = IdentifierList ( \"=\" | \":=\" ) \"range\" Expression .\n </pre>\n \n-The type of the right-hand expression in the range clause must be an array or\n-map, or a pointer to an array or map. If it is a pointer, it must not be nil.\n-The left-hand identifier list must contain one or two identifiers denoting the\n-iteration variables. The first variable is set to the current array index or\n+<p>\n+The type of the right-hand expression in the \"range\" clause must be an array,\n+slice or map, or a pointer to an array, slice or map.\n+The slice or map must not be <code>nil</code>.\n+The identifier list must contain one or two identifiers denoting the\n+iteration variables. On each iteration,\n+the first variable is set to the array or slice index or\n map key, and the second variable, if present, is set to the corresponding\n-array element or map value. The types of the array index (int) and element,\n-or of the map key and value respectively, must be assignment-compatible to\n-the iteration variables.\n+array element or map value.\n+The types of the array or slice index (always <code>int</code>)\n+and element, or of the map key and value respectively,\n+must be assignment compatible to the iteration variables.\n+</p>\n <p>\n-The iteration variables may be declared by the range clause (\":=\"), in which\n-case their scope ends at the end of the for statement block ($Declarations and\n-scope rules, Rule 3). In this case their types are the array index and element,\n-or the map key and value types, respectively.\n+The iteration variables may be declared by the \"range\" clause (\":=\"), in which\n+case their scope ends at the end of the \"for\" statement ($Declarations and\n+scope rules). In this case their types are set to\n+the array index and element types, or the map key and value types, respectively.\n+If the iteration variables are declared outside the \"for\" statement,\n+after execution their values will be those of the last iteration.\n+</p>\n \n <pre>\n var a [10]string;\n@@ -3228,27 +3266,31 @@ for key, value = range m {\n // val == map[key]\n </pre>\n \n+<p>\n If map entries that have not yet been processed are deleted during iteration,\n they will not be processed. If map entries are inserted during iteration, the\n-behavior is implementation-dependent. Likewise, if the range expression is a\n-pointer variable, the behavior of assigning to that variable is implementation-\n-dependent. Assigning to the iteration variables during iteration simply changes\n-the values of those variables for the current iteration; it does not affect any\n-subsequent iterations.\n-\n+behavior is implementation-dependent. Likewise, if the range variable is\n+assigned to during execution of the loop, the behavior is implementation-\n+dependent.\n+</p>\n \n <h3>Go statements</h3>\n \n-A go statement starts the execution of a function as an independent\n-concurrent thread of control within the same address space. The expression\n-must be a function or method call.\n+<p>\n+A \"go\" statement starts the execution of a function or method call \n+as an independent concurrent thread of control, or <i>goroutine</i>,\n+within the same address space.\n+</p>\n \n <pre class=\"grammar\">\n GoStat = \"go\" Expression .\n </pre>\n \n-Unlike with a regular function call, program execution does not wait\n+<p>\n+The expression must be a call, and\n+unlike with a regular call, program execution does not wait\n for the invoked function to complete.\n+</p>\n \n <pre>\n go Server()\n@@ -3258,9 +3300,11 @@ go func(ch chan <- bool) { for { sleep(10); ch <- true; }} (c)\n \n <h3>Select statements</h3>\n \n-A select statement chooses which of a set of possible communications\n-will proceed. It looks similar to a switch statement but with the\n+<p>\n+A \"select\" statement chooses which of a set of possible communications\n+will proceed. It looks similar to a \"switch\" statement but with the\n cases all referring to communication operations.\n+</p>\n \n <pre class=\"grammar\">\n SelectStat = \"select\" \"{\" { CommClause } \"}\" .\n@@ -3270,35 +3314,43 @@ SendExpr = Expression \"<-\" Expression .\n RecvExpr = [ Expression ( \"=\" | \":=\" ) ] \"<-\" Expression .\n </pre>\n \n+<p>\n Each communication clause acts as a block for the purpose of scoping\n (§Declarations and scope rules).\n+</p>\n <p>\n-For all the send and receive expressions in the select\n-statement, the channel expression is evaluated. Any values\n+For all the send and receive expressions in the \"select\"\n+statement, the channel expression is evaluated. Any expressions\n that appear on the right hand side of send expressions are also\n evaluated. If any of the resulting channels can proceed, one is\n chosen and the corresponding communication and statements are\n evaluated. Otherwise, if there is a default case, that executes;\n if not, the statement blocks until one of the communications can\n complete. The channels and send expressions are not re-evaluated.\n-A channel pointer may be nil, which is equivalent to that case not\n-being present in the select statement.\n+A channel pointer may be <code>nil</code>,\n+which is equivalent to that case not\n+being present in the select statement\n+except, if a send, its expression is still evaluated.\n+</p>\n <p>\n Since all the channels and send expressions are evaluated, any side\n effects in that evaluation will occur for all the communications\n-in the select.\n+in the \"select\" statement.\n+</p>\n <p>\n If the channel sends or receives an interface type, its\n communication can proceed only if the type of the communication\n clause matches that of the dynamic value to be exchanged.\n+</p>\n <p>\n-If multiple cases can proceed, a uniform fair choice is made regarding\n+If multiple cases can proceed, a uniform fair choice is made to decide\n which single communication will execute.\n <p>\n-The receive case may declare a new variable (via a \":=\" assignment). The\n-scope of such variables begins immediately after the variable identifier\n-and ends at the end of the respective \"select\" case (that is, before the\n-next \"case\", \"default\", or closing brace).\n+The receive case may declare a new variable using a short variable declaration\n+(§Short variable declarations).\n+The scope of such variables continues to the end of the\n+respective case\'s statements.\n+</p>\n \n <pre>\n var c, c1, c2 chan int;\n@@ -3337,112 +3389,129 @@ TODO: Make semantics more precise.\n \n <h3>Return statements</h3>\n \n-A return statement terminates execution of the containing function\n+<p>\n+A \"return\" statement terminates execution of the containing function\n and optionally provides a result value or values to the caller.\n+</p>\n \n <pre class=\"grammar\">\n ReturnStat = \"return\" [ ExpressionList ] .\n </pre>\n \n+<pre>\n+func procedure() {\n+\treturn\n+}\n+</pre>\n \n-There are two ways to return values from a function. The first is to\n-explicitly list the return value or values in the return statement:\n+<p>\n+There are two ways to return values from a function with a result\n+type. The first is to explicitly list the return value or values\n+in the \"return\" statement. The expressions\n+must be single-valued and assignment-compatible to the elements of\n+the result type of the function.\n+</p>\n \n <pre>\n func simple_f() int {\n-\treturn 2;\n+\treturn 2\n+}\n+\n+func complex_f1() (re float, im float) {\n+\treturn -7.0, -4.0\n }\n </pre>\n \n-A function may return multiple values.\n-The syntax of the return clause in that case is the same as\n-that of a parameter list; in particular, names must be provided for\n-the elements of the return value.\n+<p>\n+However, if the expression list in the \"return\" statement is a single call\n+to a multi-valued function, the values returned from the called function\n+will be returned from this one. The result types of the current function\n+and the called function must match.\n+</p>\n \n <pre>\n-func complex_f1() (re float, im float) {\n-\treturn -7.0, -4.0;\n+func complex_f2() (re float, im float) {\n+\treturn complex_f1()\n }\n </pre>\n \n-A second method to return values\n-is to use those names within the function as variables\n-to be assigned explicitly; the return statement will then provide no\n-values:\n+<p>\n+Another method to return values is to use the elements of the\n+result list of the function as variables. When the function begins\n+execution, these variables are initialized to the zero values for\n+their type (§The zero value). The function can assign them as\n+necessary; if the \"return\" provides no values, those of the variables\n+will be returned to the caller.\n+</p>\n \n <pre>\n-func complex_f2() (re float, im float) {\n+func complex_f3() (re float, im float) {\n \tre = 7.0;\n \tim = 4.0;\n \treturn;\n }\n </pre>\n \n-\n <h3>Break statements</h3>\n \n-Within a for, switch, or select statement, a break statement terminates\n-execution of the innermost such statement.\n+<p>\n+A \"break\" statement terminates execution of the innermost\n+\"for\", \"switch\" or \"select\" statement.\n+</p>\n \n <pre class=\"grammar\">\n-BreakStat = \"break\" [ identifier ].\n+BreakStat = \"break\" [ Label ].\n </pre>\n \n-If there is an identifier, it must be a label marking an enclosing\n-for, switch, or select statement, and that is the one whose execution\n-terminates.\n+<p>\n+If there is a label, it must be that of an enclosing\n+\"for\", \"switch\" or \"select\" statement, and that is the one whose execution\n+terminates\n+(§For statements, §Switch statements, §Select statements).\n+</p>\n \n <pre>\n L: for i < n {\n \tswitch i {\n-\tcase 5: break L\n+\t\tcase 5: break L\n \t}\n }\n </pre>\n \n-\n <h3>Continue statements</h3>\n \n-Within a for loop a continue statement begins the next iteration of the\n-loop at the post statement.\n-\n-<pre class=\"grammar\">\n-ContinueStat = \"continue\" [ identifier ].\n-</pre>\n-\n-The optional identifier is analogous to that of a break statement.\n-\n-\n-<h3>Label declarations</h3>\n-\n-A label declaration serves as the target of a goto, break or continue statement.\n+<p>\n+A \"continue\" statement begins the next iteration of the\n+innermost \"for\" loop at the post statement (§For statements).\n+</p>\n \n <pre class=\"grammar\">\n-LabelDecl = identifier \":\" .\n-</pre>\n-\n-Example:\n-\n-<pre>\n-Error:\n+ContinueStat = \"continue\" [ Label ].\n </pre>\n \n+<p>\n+The optional label is analogous to that of a \"break\" statement.\n+</p>\n \n <h3>Goto statements</h3>\n \n-A goto statement transfers control to the corresponding label statement.\n+<p>\n+A \"goto\" statement transfers control to the statement with the corresponding label.\n+</p>\n \n <pre class=\"grammar\">\n-GotoStat = \"goto\" identifier .\n+GotoStat = \"goto\" Label .\n </pre>\n \n <pre>\n goto Error\n </pre>\n \n-Executing the goto statement must not cause any variables to come into\n+<p>\n+Executing the \"goto\" statement must not cause any variables to come into\n scope that were not already in scope at the point of the goto. For\n instance, this example:\n+</p>\n \n <pre>\n goto L; // BAD\n@@ -3450,15 +3519,19 @@ v := 3;\n L:\n </pre>\n \n-is erroneous because the jump to label L skips the creation of v.\n-\n+<p>\n+is erroneous because the jump to label <code>L</code> skips\n+the creation of <code>v</code>.\n+</p>\n \n <h3>Fallthrough statements</h3>\n \n-A fallthrough statement transfers control to the first statement of the\n-next case clause in a switch statement (§Switch statements). It may only\n-be used in a switch statement, and only as the last statement in a case\n-clause of the switch statement.\n+<p>\n+A \"fallthrough\" statement transfers control to the first statement of the\n+next case clause in a \"switch\" statement (§Switch statements). It may\n+be used only as the lexically last statement in a case or default clause in a\n+\"switch\" statement.\n+</p>\n \n <pre class=\"grammar\">\n FallthroughStat = \"fallthrough\" .\n@@ -3467,19 +3540,24 @@ FallthroughStat = \"fallthrough\" .\n \n <h3>Defer statements</h3>\n \n-A defer statement invokes a function whose execution is deferred to the moment\n-when the surrounding function returns.\n+<p>\n+A \"defer\" statement invokes a function whose execution is deferred to the moment\n+the surrounding function returns.\n+</p>\n \n <pre class=\"grammar\">\n DeferStat = \"defer\" Expression .\n </pre>\n \n-The expression must be a function or method call. Each time the defer statement\n+<p>\n+The expression must be a function or method call.\n+Each time the \"defer\" statement\n executes, the parameters to the function call are evaluated and saved anew but the\n function is not invoked. Immediately before the innermost function surrounding\n-the defer statement returns, but after its return value (if any) is evaluated,\n+the \"defer\" statement returns, but after its return value (if any) is evaluated,\n each deferred function is executed with its saved parameters. Deferred functions\n are executed in LIFO order.\n+</p>\n \n <pre>\n lock(l);\n@@ -3539,55 +3617,66 @@ space allocated in the underlying array (for a slice) or map. For a slice\n \n <h3>Conversions</h3>\n \n-Conversions syntactically look like function calls of the form\n+<p>\n+<font color=red>TODO: We need to finalize the details of conversions.</font>\n+<br/>\n+Conversions look like function calls of the form\n+</p>\n \n <pre class=\"grammar\">\n T(value)\n </pre>\n \n+<p>\n where <code>T</code> is the type name of an arithmetic type or string (§Basic types),\n and <code>value</code> is the value of an expression that can be converted to a value\n of result type <code>T</code>.\n <p>\n The following conversion rules apply:\n-<p>\n+</p>\n+<ul>\n+<li>\n 1) Between integer types. If the value is a signed quantity, it is\n sign extended to implicit infinite precision; otherwise it is zero\n extended. It is then truncated to fit in the result type size.\n-For example, uint32(int8(0xFF)) is 0xFFFFFFFF. The conversion always\n-yields a valid value; there is no signal for overflow.\n-<p>\n+For example, <code>uint32(int8(0xFF))</code> is <code>0xFFFFFFFF</code>.\n+The conversion always yields a valid value; there is no signal for overflow.\n+</li>\n+<li>\n 2) Between integer and floating point types, or between floating point\n types. To avoid overdefining the properties of the conversion, for\n now it is defined as a ``best effort\'\' conversion. The conversion\n always succeeds but the value may be a NaN or other problematic\n result. <font color=red>TODO: clarify?</font>\n-<p>\n+</li>\n+<li>\n 3) Strings permit two special conversions.\n-<p>\n+</li>\n+<li>\n 3a) Converting an integer value yields a string containing the UTF-8\n representation of the integer.\n (TODO: this one could be done just as well by a library.)\n-</p>\n \n <pre>\n string(0x65e5) // \"\\u65e5\"\n </pre>\n \n-<p>\n-3b) Converting an array of <code>uint8s</code> yields a string whose successive\n-bytes are those of the array.\n-(Recall <code>byte</code> is a synonym for <code>uint8</code>.)\n-</p>\n+</li>\n+<li>\n+3b) Converting an array or slice of bytes yields a string whose successive\n+bytes are those of the array/slice.\n \n <pre>\n string([]byte(\'h\', \'e\', \'l\', \'l\', \'o\')) // \"hello\"\n </pre>\n+</li>\n+</ul>\n \n <p>\n-There is no linguistic mechanism to convert between pointers\n-and integers. A library may be provided under restricted circumstances\n-to acccess this conversion in low-level code.\n+There is no linguistic mechanism to convert between pointers and integers.\n+The <code>unsafe</code> package\n+implements this functionality under\n+restricted circumstances (§Package <code>unsafe</code>).\n <font color=red>\n TODO: Do we allow interface/ptr conversions in this form or do they\n have to be written as type guards? (§Type guards)\n@@ -3597,52 +3686,66 @@ have to be written as type guards? (§Type guards)\n \n <h3>Allocation</h3>\n \n-The built-in function \"new\" takes a type \"T\" and returns a value of type \"*T\".\n+<p>\n+The built-in function <code>new</code> takes a type <code>T</code> and\n+returns a value of type <code>*T</code>.\n The memory is initialized as described in the section on initial values\n (§The zero value).\n+</p>\n \n <pre>\n new(T)\n </pre>\n \n+<p>\n For instance\n+</p>\n \n <pre>\n type S struct { a int; b float }\n new(S)\n </pre>\n \n-dynamically allocates memory for a variable of type S, initializes it\n-(a=0, b=0.0), and returns a value of type *S pointing to that variable.\n-\n <p>\n-<font color=red>\n-TODO Once this has become clearer, connect new() and make() (new() may be\n-explained by make() and vice versa).\n-</font>\n+dynamically allocates memory for a variable of type <code>S</code>,\n+initializes it (<code>a=0</code>, <code>b=0.0</code>),\n+and returns a value of type <code>*S</code> containing the address\n+of the memory.\n+</p>\n \n-<h3>Making slices, maps, and channels</h3>\n+<h3>Making slices, maps and channels</h3>\n \n-The built-in function \"make\" takes a type \"T\", optionally followed by a\n-type-specific list of expressions. It returns a value of type \"T\". \"T\"\n-must be a slice, map, or channel type.\n+<p>\n+Slices, maps and channels are reference types that do not require the\n+extra indirection of an allocation with <code>new</code>.\n+The built-in function <code>make</code> takes a type <code>T</code>,\n+which must be a slice, map or channel type,\n+optionally followed by a type-specific list of expressions.\n+It returns a value of type <code>T</code> (not <code>*T</code>).\n The memory is initialized as described in the section on initial values\n (§The zero value).\n+</p>\n \n <pre>\n make(T [, optional list of expressions])\n </pre>\n \n+<p>\n For instance\n+</p>\n \n <pre>\n make(map[string] int)\n </pre>\n \n+<p>\n creates a new map value and initializes it to an empty map.\n+</p>\n \n-The only defined parameters affect sizes for allocating slices, maps, and\n+<p>\n+The parameters affect sizes for allocating slices, maps, and\n buffered channels:\n+</p>\n \n <pre>\n s := make([]int, 10, 100); # slice with len(s) == 10, cap(s) == 100\n@@ -3650,11 +3753,6 @@ c := make(chan int, 10); # channel with a buffer size of 10\n m := make(map[string] int, 100); # map with initial space for 100 elements\n </pre>\n \n-<font color=red>\n-TODO Once this has become clearer, connect new() and make() (new() may be\n-explained by make() and vice versa).\n-</font>\n-\n <hr/>\n \n <h2>Packages</h2>\n@@ -3743,7 +3841,7 @@ func generate(ch chan <- int) {\n \n // Copy the values from channel \'in\' to channel \'out\',\n // removing those divisible by \'prime\'.\n-func filter(in chan <- int, out *<-chan int, prime int) {\n+func filter(in chan <- int, out <-chan int, prime int) {\n \tfor {\n \t\ti := <-in; // Receive value of new variable \'i\' from \'in\'.\n \t\tif i % prime != 0 {\n@@ -3813,29 +3911,44 @@ t.f == 0.0\n t.next == nil\n </pre>\n \n+<p>\n+The same would also be true after\n+</p>\n+\n+<pre>\n+var t T\n+</pre>\n+\n <h3>Program execution</h3>\n <p>\n A package with no imports is initialized by assigning initial values to\n-all its global variables in declaration order and then calling any init()\n-functions defined in its source. Since a package may contain more\n-than one source file, there may be more than one init() function, but\n+all its package-level variables in declaration order and then calling any\n+package-level function with the name and signature of\n+</p>\n+<pre>\n+func init()\n+</pre>\n+<p>\n+defined in its source. Since a package may contain more\n+than one source file, there may be more than one\n+<code>init()</code> function in a package, but\n only one per source file.\n </p>\n <p>\n Initialization code may contain \"go\" statements, but the functions\n they invoke do not begin execution until initialization of the entire\n program is complete. Therefore, all initialization code is run in a single\n-thread of execution.\n+goroutine.\n </p>\n <p>\n-Furthermore, an \"init()\" function cannot be referred to from anywhere\n-in a program. In particular, \"init()\" cannot be called explicitly, nor\n-can a pointer to \"init\" be assigned to a function variable).\n+An <code>init()</code> function cannot be referred to from anywhere\n+in a program. In particular, <code>init()</code> cannot be called explicitly,\n+nor can a pointer to <code>init</code> be assigned to a function variable.\n </p>\n <p>\n If a package has imports, the imported packages are initialized\n before initializing the package itself. If multiple packages import\n-a package P, P will be initialized only once.\n+a package <code>P</code>, <code>P</code> will be initialized only once.\n </p>\n <p>\n The importing of packages, by construction, guarantees that there can\n@@ -3843,19 +3956,19 @@ be no cyclic dependencies in initialization.\n </p>\n <p>\n A complete program, possibly created by linking multiple packages,\n-must have one package called main, with a function\n+must have one package called <code>main</code>, with a function\n </p>\n \n <pre>\n-func main() { ... }\n+func main() { ... }\n </pre>\n \n <p>\n-defined. The function <code>main.main()</code> takes no arguments and returns no\n-value.\n+defined.\n+The function <code>main.main()</code> takes no arguments and returns no value.\n </p>\n <p>\n-Program execution begins by initializing the main package and then\n+Program execution begins by initializing the <code>main</code> package and then\n invoking <code>main.main()</code>.\n </p>\n <p>\n@@ -3869,10 +3982,11 @@ When main.main() returns, the program exits.\n <h3>Package <code>unsafe</code></h3>\n \n <p>\n-The built-in package <code>unsafe</code>, known to the compiler, provides facilities\n-for low-level programming including operations that violate the type\n-system. A package using <code>unsafe</code> must be vetted manually for type safety.\n-The package provides the following interface:\n+The built-in package <code>unsafe</code>, known to the compiler,\n+provides facilities for low-level programming including operations\n+that violate the type system. A package using <code>unsafe</code>\n+must be vetted manually for type safety. The package provides the\n+following interface:\n </p>\n \n <pre class=\"grammar\">\n@@ -3975,6 +4089,8 @@ cap() does not work on maps or chans.\n <br/>\n len() does not work on chans.\n <br/>\n+select doesn\'t check dynamic type of interfaces.\n+<br/>\n Conversions work for any type; doc says only arithmetic types and strings.\n </font>\n </p>\n```
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/96750f130c64cf90777962cb6d7701a9faaee9f6](https://github.com/golang/go/commit/96750f130c64cf90777962cb6d7701a9faaee9f6)
## 元コミット内容
このコミットの元のメッセージは「most of the rest. only the package section is untouched.」と非常に簡潔です。これは、Go言語仕様の大部分を更新したことを示唆しており、特に「package」セクションのみが変更されていないことを明記しています。これは、Go言語の初期段階において、言語仕様の策定が活発に行われていた時期のコミットであることを示しています。
## 変更の背景
このコミットは、Go言語が一般に公開される前の2009年2月に行われたものであり、Go言語の設計と仕様の初期段階における重要な洗練作業の一環です。当時のGo言語はまだ開発途上にあり、言語の構文、セマンティクス、および動作に関する多くの側面が定義され、文書化されている最中でした。
変更の主な背景は以下の通りと考えられます。
1. **言語仕様の明確化と厳密化**: Go言語の設計者たちは、言語の動作を曖昧さなく、かつ厳密に定義することを目指していました。このコミットは、特にステートメントの構文、セミコロンの扱い、型変換のルール、メモリ割り当てのメカニズムなど、言語の基本的な要素に関する記述をより正確にするためのものです。
2. **一貫性の向上**: 言語の異なる部分間での一貫性を確保するため、既存の記述を修正し、新しい概念(例: `unsafe` パッケージ)を導入する必要がありました。
3. **並行処理モデルの明確化**: Go言語の主要な特徴である並行処理(goroutineとchannel)に関する記述も、より詳細かつ正確に定義されています。特に `go` ステートメントや `select` ステートメントの動作に関する説明が強化されています。
4. **初期のフィードバックの反映**: 内部でのレビューやプロトタイプ実装を通じて得られたフィードバックを反映し、仕様を改善した可能性があります。
このコミットは、Go言語が安定した、十分に定義された言語として公開されるための基盤を固める上で不可欠なステップでした。
## 前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語の基本的な概念と、一般的なプログラミング言語の知識が必要です。
1. **Go言語の基本的な構文**:
* **関数呼び出し**: `f(a, b, c)` のような形式で関数を実行する。
* **代入**: 変数に値を設定する操作。Goには単一代入と多重代入があります。
* **制御フロー文**:
* **`if` 文**: 条件に基づいてコードブロックを実行する。
* **`switch` 文**: 式の値に基づいて複数のケースから一つを選択して実行する。
* **`for` 文**: ループ処理を行う。Goには `for` ループのみがあり、C言語のような `while` や `do-while` はありません。`range` キーワードを使ったイテレーションも可能です。
* **`break` 文**: ループや `switch`、`select` 文を終了する。
* **`continue` 文**: ループの現在のイテレーションをスキップし、次のイテレーションに進む。
* **`goto` 文**: 指定されたラベルに無条件にジャンプする。
* **`fallthrough` 文**: `switch` 文のケースで、次のケースに処理を継続させる。
* **`defer` 文**: 現在の関数の終了時に指定された関数を遅延実行する。
* **セミコロンの自動挿入 (Automatic Semicolon Insertion - ASI)**: Go言語では、特定の場所で改行がある場合にコンパイラが自動的にセミコロンを挿入します。これにより、C言語のように手動でセミコロンを記述する手間が省けますが、そのルールを理解しておく必要があります。
2. **Goの並行処理モデル**:
* **Goroutine**: Goランタイムによって管理される軽量なスレッド。`go` キーワードを使って関数をgoroutineとして実行できます。
* **Channel**: goroutine間で値を安全に送受信するための通信メカニズム。
* **`select` 文**: 複数のチャネル操作の中から準備ができたものを選択して実行する。
3. **Goの型システム**:
* **ゼロ値 (Zero Value)**: Goの変数は宣言時に自動的にその型のゼロ値で初期化されます(例: `int` は `0`、`string` は `""`、ポインタは `nil`)。
* **型変換 (Conversions)**: ある型から別の型へ値を変換する操作。
* **`new` と `make`**:
* `new`: 組み込み関数で、指定された型のゼロ値で初期化された新しいメモリを割り当て、その型へのポインタを返します。
* `make`: 組み込み関数で、スライス、マップ、チャネルといった参照型を初期化し、その型の値を返します。`new` とは異なり、これらの型に特化した初期化を行います。
4. **パッケージと初期化**:
* **パッケージ**: Goのコードを整理するための単位。
* **`init()` 関数**: 各パッケージに定義できる特別な関数で、パッケージが初期化される際に自動的に実行されます。
* **`main` パッケージと `main()` 関数**: 実行可能なGoプログラムのエントリポイント。
5. **`unsafe` パッケージ**:
* Go言語の型安全性を意図的にバイパスするための機能を提供するパッケージ。ポインタと整数間の変換など、低レベルな操作を可能にしますが、使用には細心の注意が必要です。
これらの概念を理解することで、コミットがGo言語の仕様にどのような影響を与え、なぜこれらの変更が必要とされたのかを深く把握することができます。
## 技術的詳細
このコミットは、`doc/go_spec.html` におけるGo言語の仕様記述を広範囲にわたって更新しています。以下に主要な変更点を技術的な観点から詳細に解説します。
### 1. Calls (関数呼び出し)
* **変更前**: 関数または関数変数 `f` の関数型 `F` が与えられた場合、`f(a, b, c)` は引数 `a, b, c` で関数を呼び出す、と記述されていました。
* **変更後**: 式 `f` が関数型 `F` である場合、`f(a1, a2, ... an)` は `f` を引数 `a1, a2, ... an` で呼び出す、と変更されました。
* **ポイント**: 「関数または関数変数」という具体的な表現から「式」というより一般的な表現に変わり、関数呼び出しの対象がより広範な式であることを明確にしています。また、引数が「単一値の式 (single-valued expressions)」である必要があるという制約が追加されました。
### 2. Statements (文)
このセクションは、Go言語の文法定義において最も大きな変更の一つです。
* **文法定義の再構築**:
* `Statement` の定義が `Statement = { Label ":" } UnlabeledStatement .` となり、文がオプションでラベルを持つことができるようになりました。
* `Label` が `identifier` と定義され、ラベルが識別子であることを明確にしました。
* `UnlabeledStatement` が導入され、ラベルを持たない文のカテゴリが定義されました。
* `StatementList` の定義が `Statement { Separator Statement } .` となり、`Separator` が `[ ";" ]` と定義されました。これは、文の区切りがセミコロンであり、それが省略可能であることを示しています。
* **セミコロンの省略ルール**:
* **変更前**: セミコロンが省略できるケースとして、閉じ括弧 `)`、閉じ波括弧 `}`、ラベル宣言の直後が挙げられていました。
* **変更後**: セミコロンが省略できるのは、前の文が宣言リストの閉じ括弧 `)`、型宣言の閉じ波括弧 `}`、またはブロック(`switch` や `select` を含む)の閉じ波括弧 `}` で終わる場合のみ、とより厳密に定義されました。これにより、セミコロンの自動挿入 (ASI) のルールがより明確になりました。
* **ラベル付き文**: ラベル付き文が `goto`、`break`、`continue` 文のターゲットになり得ることが明記されました。
### 3. Empty statements (空文)
* 空文が何もしないこと、および文リストが空文を追加することでセミコロンで「終端」できることが明確化されました。
### 4. Expression statements (式文)
* `<-ch` (チャネル受信) が式文の例として追加され、チャネル操作も文脈で出現し得ることが示されました。
* 以前の「TODO: specify restrictions. 6g only appears to allow calls here.」というコメントが削除され、式文の制限が明確になったことを示唆しています。
### 5. IncDec statements (インクリメント/デクリメント文)
* オペランドが「理想的な数値 `1`」で増減されることが明確化されました。
* オペランドが変数、ポインタ間接参照、フィールドセレクタ、またはインデックス式でなければならないという制約が追加されました。
* 「Both operators apply to integer and floating point types only.」という記述が削除され、より一般的な型に適用される可能性を示唆しています。
* 「Note that increment and decrement are statements, not expressions. For instance, "x++" cannot be used as an operand in an expression.」という重要な注意書きが削除されましたが、これはGo言語の設計がこの時点で固まったことを示唆しています。実際、Goでは `x++` は式ではなく文です。
### 6. Assignments (代入)
* **左辺オペランド**: 各左辺オペランドが変数、ポインタ間接参照、フィールドセレクタ、またはインデックス式でなければならないことが明確化されました。
* **複合代入演算子 (`op=`)**: `x op= y` の形式の代入操作が `x = x op y` と同等であり、`x` が一度だけ評価されることが明確に記述されました。`op=` が単一のトークンであることも強調されています。
* **タプル代入**:
* 多値関数からの戻り値やチャネル/マップ操作の結果を複数の変数に代入する形式が詳細化されました。
* 右辺オペランドが単一の多値式である場合(例: `x, y = f()`)と、右辺の各式が単一値である場合(例: `a, b = b, a`)の2つの形式が明確に区別されました。
* マップからの値の取得(`value, present = map_var[key]`)やマップからの値の削除(`map_var[key] = value, false`)に関する特別なケースの記述が削除されました。これは、これらの操作が言語のより一般的なタプル代入のルールに統合されたか、または別のセクションで扱われるようになったことを示唆しています。
* **代入互換性**: 代入において、各値の型が代入されるオペランドの型と「代入互換性 (assignment compatible)」でなければならないことが強調されました。
### 7. If statements (if 文)
* `if` 文が式の手前に短い変数宣言を含むことができること(`x := f()` のような形式)が明確化されました。
* 宣言された変数のスコープが `if` 文の終わりまで続くことが強調されました。
### 8. Switch statements (switch 文)
* **動作の詳細化**:
* 式が評価され、`case` 式と比較されることで、どのブランチが実行されるかが決定されることが明確化されました。
* `case` 式は定数である必要がなく、上から下へ評価され、最初に一致したものが実行されることが記述されました。
* `default` ケースの動作(一致する `case` がない場合に実行される)と、`default` ケースが `switch` 文内のどこにでも出現できることが明確化されました。
* **`fallthrough` の動作**: `case` または `default` 句の最後の文のみが `fallthrough` 文であり得ること、そしてそれが次の句の最初の文に制御を移すことを明確にしました。
* **スコープ**: 各 `case` 句がスコープ目的でブロックとして機能することが強調されました。
* **短い変数宣言**: `switch` 文が式の手前に短い変数宣言を含むことができること、およびそのスコープが `switch` 文の終わりまで続くことが明確化されました。
### 9. For statements (for 文)
* **基本的な `for` ループ**: 条件が省略された場合、`true` と同等であることが明確化されました。
* **`for` 句 (`init; cond; post`)**:
* `init` ステートメントが `for` ループの開始前に一度だけ実行されること、`post` ステートメントがブロックの各実行後に実行されることが明確化されました。
* `init` ステートメントは短い変数宣言を含むことができるが、`post` ステートメントはできないことが強調されました。
* `for` 句のどの要素も空にできるが、セミコロンは条件のみの場合を除いて必須であることが明確化されました。
* **`range` 句**:
* `range` 句が配列、スライス、マップ、またはそれらへのポインタをイテレートすることが明確化されました。
* スライスまたはマップが `nil` であってはならないという制約が追加されました。
* イテレーション変数の型が、配列/スライスのインデックス(常に `int`)と要素、またはマップのキーと値の型にそれぞれ設定されることが明確化されました。
* イテレーション変数が `range` 句で宣言された場合(`:=`)、そのスコープが `for` 文の終わりまで続くことが明確化されました。
* イテレーション変数が `for` 文の外で宣言された場合、ループ実行後の値は最後のイテレーションの値になることが追加されました。
* マップのイテレーション中にエントリが削除または挿入された場合の動作が「実装依存」であることが明確化されました。
### 10. Go statements (go 文)
* `go` 文が関数またはメソッド呼び出しを「独立した並行制御スレッド、すなわち *goroutine*」として開始することが明確化されました。
* 式が呼び出しでなければならないこと、そして通常の呼び出しとは異なり、プログラムの実行は呼び出された関数が完了するのを待たないことが強調されました。
### 11. Select statements (select 文)
* **動作の詳細化**:
* `select` 文内のすべての送受信式において、チャネル式が評価されることが明確化されました。
* 複数のケースが進行可能な場合、どの単一の通信が実行されるかを決定するために「均一で公平な選択 (uniform fair choice)」が行われることが記述されました。
* チャネルポインタが `nil` であり得る場合、そのケースは `select` 文に存在しないのと同等であることが明確化されました(ただし、送信の場合はその式は評価される)。
* すべてのチャネルと送信式が評価されるため、その評価における副作用は `select` 文内のすべての通信で発生することが強調されました。
* **短い変数宣言**: 受信ケースが短い変数宣言を使用して新しい変数を宣言できること、およびその変数のスコープが対応するケースの文の終わりまで続くことが明確化されました。
### 12. Return statements (return 文)
* **戻り値の指定方法**:
* 明示的に戻り値をリストする形式(例: `return 2`)と、関数の結果リストの要素を変数として使用する形式(名前付き戻り値、例: `re = 7.0; im = 4.0; return;`)の2つの方法が明確に記述されました。
* 式リストが多値関数への単一の呼び出しである場合、呼び出された関数から返された値が現在の関数から返されることが追加されました。この場合、現在の関数と呼び出された関数の結果型が一致する必要があることも明記されました。
### 13. Break statements (break 文)
* `break` 文が「最も内側の `for`、`switch`、または `select` 文」の実行を終了することが明確化されました。
* オプションのラベルがある場合、それが囲む `for`、`switch`、または `select` 文のラベルでなければならないことが強調されました。
### 14. Continue statements (continue 文)
* `continue` 文が「最も内側の `for` ループ」の次のイテレーションを開始することが明確化されました。
* オプションのラベルがある場合、それが `break` 文のラベルと同様に機能することが記述されました。
### 15. Goto statements (goto 文)
* `goto` 文の実行が、`goto` の時点ですでにスコープ内にない変数をスコープ内に入れる原因となってはならないという重要な制約が明確化されました。
### 16. Fallthrough statements (fallthrough 文)
* `fallthrough` 文が `switch` 文の次のケース句の最初の文に制御を移すこと、そしてそれが `switch` 文の `case` または `default` 句の「字句的に最後の文」としてのみ使用できることが明確化されました。
### 17. Defer statements (defer 文)
* `defer` 文が関数またはメソッド呼び出しでなければならないこと、および `defer` 文が実行されるたびに、関数呼び出しのパラメータが評価され、新しく保存されるが、関数自体は呼び出されないことが明確化されました。
* 遅延関数が LIFO (Last-In, First-Out) 順で実行されることが強調されました。
### 18. Conversions (型変換)
* **文法**: `T(value)` の形式で型変換が行われることが明確化されました。
* **ルール**:
* 整数型間の変換: 符号拡張またはゼロ拡張が行われ、結果の型サイズに合わせて切り捨てられることが詳細に記述されました。オーバーフローのシグナルはないことも明記されました。
* 整数と浮動小数点型、または浮動小数点型間の変換: 「ベストエフォート」変換であり、常に成功するが、NaNなどの問題のある結果になる可能性があることが記述されました。
* 文字列の特殊な変換:
* 整数値からUTF-8表現を含む文字列への変換(例: `string(0x65e5)` は `"日"`)。
* `uint8` の配列またはスライスから、そのバイト列を連続して含む文字列への変換(例: `string([]byte('h', 'e', 'l', 'l', 'o'))` は `"hello"`)。
* **ポインタと整数間の変換**: 言語メカニズムとしては存在しないが、`unsafe` パッケージが制限された状況下でこの機能を提供することが明確に記述されました。
### 19. Allocation (`new`)
* 組み込み関数 `new` が型 `T` を取り、型 `*T` の値を返すことが明確化されました。
* 割り当てられたメモリがゼロ値で初期化されることが強調されました。
### 20. Making slices, maps, and channels (`make`)
* スライス、マップ、チャネルが参照型であり、`new` による追加の間接参照を必要としないことが明確化されました。
* 組み込み関数 `make` が型 `T`(スライス、マップ、チャネル型でなければならない)を取り、型 `T` の値を返すこと(`*T` ではない)が強調されました。
* メモリがゼロ値で初期化されることが記述されました。
* `make` のパラメータが、スライス、マップ、バッファ付きチャネルの割り当てサイズに影響を与えることが明確化されました。
### 21. Program execution (プログラム実行)
* **パッケージ初期化**:
* インポートのないパッケージは、すべてのパッケージレベル変数が宣言順に初期値で割り当てられ、その後 `init()` 関数が呼び出されることで初期化されることが詳細に記述されました。
* `init()` 関数は明示的に呼び出すことも、ポインタを割り当てることもできないことが強調されました。
* 初期化コードは `go` ステートメントを含むことができるが、それらが呼び出す関数はプログラム全体の初期化が完了するまで実行を開始しないこと、したがってすべての初期化コードは単一の「goroutine」で実行されることが明確化されました。
* **インポートされたパッケージの初期化**: インポートされたパッケージは、それらをインポートするパッケージ自体が初期化される前に初期化されること、および複数のパッケージが `P` をインポートしても `P` は一度だけ初期化されることが明確化されました。
* **`main` パッケージと `main()` 関数**: 完全なプログラムは `main` と呼ばれるパッケージを持ち、`func main() { ... }` という関数を定義しなければならないことが明確化されました。プログラムの実行は `main` パッケージの初期化から始まり、その後 `main.main()` が呼び出されることも記述されました。
### 22. Package `unsafe`
* `unsafe` パッケージが、コンパイラに認識されており、型システムに違反する操作を含む低レベルプログラミングのための機能を提供することが明確に記述されました。
* `unsafe` を使用するパッケージは、型安全性のために手動で精査されなければならないことが強調されました。
* `unsafe` パッケージが提供するインターフェース(`Pointer` 型、`Alignof`、`Offsetof`、`Sizeof` 関数)が記述されました。
### 全体的な変更の傾向
このコミットは、Go言語の仕様をより厳密で、詳細で、曖昧さのないものにするための大規模な作業を示しています。特に、文法定義の形式化、セミコロンの自動挿入ルールの明確化、並行処理プリミティブの動作の詳述、そして `unsafe` パッケージの導入は、Go言語の初期設計における重要なマイルストーンと言えます。多くの「TODO」コメントが削除または更新されていることから、仕様策定が着実に進んでいたことが伺えます。
## コアとなるコードの変更箇所
このコミットは、Go言語の仕様書である `doc/go_spec.html` ファイルのみを変更しています。したがって、「コアとなるコード」とは、このHTMLドキュメント内のGo言語の文法定義と説明文そのものを指します。
主要な変更箇所は以下の通りです。
1. **`<h3>Calls</h3>` セクション**:
* 関数呼び出しの対象が「関数または関数変数」から「式」に一般化され、引数が「単一値の式」である必要があるという制約が追加されました。
* `f(a, b, c)` から `f(a1, a2, ... an)` へと引数の表記が変更されました。
2. **`<h2>Statements</h2>` セクション**:
* `Statement` の文法定義が大幅に再構築されました。
* `Statement = { Label ":" } UnlabeledStatement .`
* `Label = identifier .`
* `UnlabeledStatement = Declaration | EmptyStat | SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat | FallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat | DeferStat .`
* `StatementList` と `Separator` の定義が追加され、セミコロンの自動挿入ルールがより厳密に記述されました。
* セミコロンの省略ルールに関する箇条書きが修正され、より具体的な条件が示されました。
3. **`<h3>Expression statements</h3>` セクション**:
* 例として `<-ch` (チャネル受信) が追加されました。
* `<font color=red>TODO: specify restrictions. 6g only appears to allow calls here.</font>` というコメントが削除されました。
4. **`<h3>IncDec statements</h3>` セクション**:
* インクリメント/デクリメントのオペランドに関する制約が追加されました。
* 「Both operators apply to integer and floating point types only.」という記述が削除されました。
* 「Note that increment and decrement are statements, not expressions.」という記述が削除されました。
5. **`<h3>Assignments</h3>` セクション**:
* 左辺オペランドに関する制約が明確化されました。
* 複合代入演算子 (`op=`) の動作が詳細に記述されました。
* タプル代入の形式が2つに分類され、それぞれ詳細な説明が追加されました。
* マップからの値の取得と削除に関する特別な例が削除されました。
6. **`<h3>If statements</h3>` セクション**:
* 短い変数宣言 (`if x := f(); ...`) の記述が追加され、そのスコープが明確化されました。
7. **`<h3>Switch statements</h3>` セクション**:
* `switch` 文の動作、`case` の評価順序、`default` ケースの配置、`fallthrough` の使用に関する詳細な説明が追加されました。
* 短い変数宣言 (`switch x := f(); ...`) の記述が追加されました。
8. **`<h3>For statements</h3>` セクション**:
* `for` 句 (`init; cond; post`) の動作と、`init` ステートメントでの短い変数宣言に関する詳細が追加されました。
* `range` 句の動作が大幅に詳細化され、配列、スライス、マップ、ポインタへの適用、イテレーション変数のスコープ、マップのイテレーション中の変更に関する動作が記述されました。
9. **`<h3>Go statements</h3>` セクション**:
* `go` 文が「goroutine」を開始することが明記され、その動作が詳細化されました。
10. **`<h3>Select statements</h3>` セクション**:
* `select` 文の動作、チャネル式の評価、`nil` チャネルの扱い、副作用、公平な選択、短い変数宣言に関する詳細が追加されました。
11. **`<h3>Return statements</h3>` セクション**:
* 戻り値の指定方法が2つの形式(明示的なリストと名前付き戻り値)に分類され、それぞれ詳細な説明が追加されました。
* 多値関数からの戻り値をそのまま返すケースが追加されました。
12. **`<h3>Break statements</h3>`、`<h3>Continue statements</h3>`、`<h3>Goto statements</h3>`、`<h3>Fallthrough statements</h3>`、`<h3>Defer statements</h3>` セクション**:
* それぞれの文の動作、ラベルの適用範囲、特定の制約(例: `goto` でのスコープのスキップ、`fallthrough` の位置)に関する記述がより明確化されました。
13. **`<h3>Conversions</h3>` セクション**:
* 型変換のルールが詳細化され、特に整数型間の変換と文字列への特殊な変換(整数からUTF-8、バイト配列/スライスから文字列)が追加されました。
* ポインタと整数間の変換に `unsafe` パッケージが関与することが明記されました。
14. **`<h3>Allocation</h3>` (`new`) および `<h3>Making slices, maps, and channels</h3>` (`make`) セクション**:
* `new` と `make` の動作、戻り値の型、初期化に関する記述がより正確になりました。
* `new` と `make` の違いが明確化されました。
15. **`<h3>Program execution</h3>` セクション**:
* パッケージの初期化プロセス、`init()` 関数の動作と制約、`main` パッケージと `main()` 関数の役割に関する詳細な説明が追加されました。
* 初期化コードが単一の「goroutine」で実行されることが明記されました。
16. **`<h3>Package <code>unsafe</code></h3>` セクション**:
* `unsafe` パッケージに関する新しいセクションが追加され、その目的と提供するインターフェースが記述されました。
これらの変更は、Go言語の仕様が初期段階から成熟に向かう過程で、言語の動作をより正確かつ包括的に定義しようとする努力を反映しています。
## コアとなるコードの解説
このコミットにおける「コアとなるコード」は、Go言語の仕様書 `doc/go_spec.html` そのものです。このドキュメントの変更は、Go言語のコンパイラやランタイムの動作に直接影響を与えるものであり、Goプログラマーが言語の挙動を理解するための最も権威ある情報源となります。
変更の解説は以下の通りです。
1. **文法定義の厳密化と明確化**:
* `Statement` の文法定義が `Label` と `UnlabeledStatement` を導入することで、より構造化され、ラベル付き文の概念が明確になりました。これは、`break`、`continue`、`goto` といった制御フロー文がラベルをターゲットにできるGoの機能の基盤となります。
* `StatementList` と `Separator` の導入により、Goのセミコロン自動挿入 (ASI) ルールが非常に詳細かつ厳密に定義されました。これにより、プログラマーはいつセミコロンを省略できるのか、いつ必須なのかを正確に理解できるようになります。これは、Goコードのフォーマットと可読性に大きな影響を与えます。
2. **制御フロー文の動作の詳述**:
* `if`、`switch`、`for` 文における「短い変数宣言 (`:=`)」の導入とそのスコープの明確化は、Goのイディオムにおける一般的なパターンを仕様レベルでサポートするものです。これにより、一時変数を宣言しつつ条件やループを制御するコードがより簡潔に記述できるようになります。
* `switch` 文の `case` 評価順序、`default` ケースの柔軟な配置、そして `fallthrough` の厳密な使用条件の定義は、`switch` 文の強力な機能を安全かつ予測可能に利用するために不可欠です。
* `for` 文の `range` 句に関する詳細な記述は、配列、スライス、マップのイテレーションの挙動、特にイテレーション中のコレクションの変更やイテレーション変数のスコープといった、プログラマーが陥りやすい落とし穴を解消する上で重要です。
3. **並行処理プリミティブの精緻化**:
* `go` 文が「goroutine」を開始するという明確な定義は、Goの並行処理モデルの核心をなす概念を確立するものです。
* `select` 文の動作に関する詳細な説明(チャネル式の評価、公平な選択、`nil` チャネルの挙動、副作用)は、複雑な並行処理ロジックを記述する上で、その予測可能性と信頼性を保証するために極めて重要です。
4. **型システムとメモリ管理の基礎の確立**:
* `new` と `make` の明確な区別とそれぞれの役割の定義は、Goにおけるメモリ割り当てと参照型の初期化の理解に不可欠です。`new` がゼロ値で初期化されたポインタを返すのに対し、`make` がスライス、マップ、チャネルといった参照型を適切に初期化してその型の値を返すという違いは、Goのメモリモデルの基礎を形成します。
* 型変換のルール、特に整数型間の変換や文字列への特殊な変換の明確化は、Goの型安全な性質を維持しつつ、必要な場面での柔軟性を提供します。
5. **`unsafe` パッケージの導入**:
* `unsafe` パッケージの仕様への追加は、Goが型安全性を重視しつつも、必要に応じて低レベルな操作を可能にする「エスケープハッチ」を提供することを示しています。これは、システムプログラミングや特定の最適化が必要な場合にGoを使用する上で重要な要素ですが、その使用には型安全性の手動での検証が必要であるという警告も含まれています。
6. **パッケージ初期化プロセスの詳細化**:
* パッケージの初期化順序、`init()` 関数の役割と制約、`main` パッケージの動作に関する詳細な記述は、Goプログラムの起動と実行フローを理解する上で不可欠です。特に、`init()` 関数が明示的に呼び出せないことや、初期化コードが単一のgoroutineで実行されるという点は、Goの設計思想を反映しています。
このコミットは、Go言語がその後の安定したバージョンへと進化していく上で、言語の基盤となるルールと挙動を確立した非常に重要なステップでした。仕様の明確化は、コンパイラの実装者、ツール開発者、そしてGoプログラマー全員にとって、言語を正確に理解し、効果的に利用するための指針となります。
## 関連リンク
このコミットはGo言語の初期の仕様策定に関するものであり、特定の関連する公開された議論やイシューは特定が困難です。しかし、Go言語の設計思想や歴史に関する一般的な情報源が関連します。
* **The Go Programming Language Specification**:
* 現在のGo言語仕様の公式ドキュメント。このコミットで変更された `doc/go_spec.html` の後継にあたります。
* [https://go.dev/ref/spec](https://go.dev/ref/spec)
* **Go Blog - The Go Programming Language**:
* Go言語の歴史や設計に関する公式ブログ記事。
* [https://go.dev/blog/](https://go.dev/blog/)
## 参考にした情報源リンク
* **Go言語の公式ドキュメント**:
* Go言語仕様書 (`doc/go_spec.html` の内容)
* Go言語のブログ記事や設計に関するドキュメント
* **Git Diff Analysis**:
* 提供されたコミットの `diff` 出力。
* **一般的なプログラミング言語の概念**:
* コンパイラ、文法、セマンティクス、制御フロー、型システム、メモリ管理に関する一般的な知識。
これらの情報源を基に、コミットの変更内容を詳細に分析し、その背景と技術的意味合いを解説しました。