]> Cypherpunks repositories - gostls13.git/commitdiff
doc/go1: most of the simple language changes
authorRob Pike <r@golang.org>
Fri, 9 Dec 2011 00:39:05 +0000 (16:39 -0800)
committerRob Pike <r@golang.org>
Fri, 9 Dec 2011 00:39:05 +0000 (16:39 -0800)
R=rsc, adg, r
CC=golang-dev
https://golang.org/cl/5477044

doc/go1.html
doc/go1.tmpl
doc/progs/go1.go

index 642f610b4b344f304069db130ea3b610f10a580b..4ac6924912cdac6802c638d3f57d5d18d89b712a 100644 (file)
@@ -31,17 +31,92 @@ r60 to compile and run under Go 1. Finally, it outlines the new
 <code>go</code> command for building Go programs and the new binary
 release process being introduced. Most of these topics have more
 thorough presentations elsewhere; such documents are linked below.
+</p>
 
 <h2 id="language">Changes to the language</h2>
 
 <h3 id="append">Append</h3>
 
+<p>
+The <code>append</code> built-in function is variadic, so one can
+append to a byte slice using the <code>...</code> syntax in the
+call.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+-->    greeting := []byte{}
+    greeting = append(greeting, []byte(&#34;hello &#34;)...)
+</pre>
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice; the conversion is no longer necessary:
+</p>
+
+<pre><!--{{code "progs/go1.go" `/append.*world/`}}
+-->    greeting = append(greeting, &#34;world&#34;...)
+</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
 <h3 id="close">Close</h3>
 
+<p>
+The <code>close</code> built-in function lets a sender tell a receiver
+that no more data will be transmitted on the channel.  In Go 1 the
+type system enforces the directionality when possible: it is illegal
+to call <code>close</code> on a receive-only channel:
+</p>
+
+<pre>
+    var c chan int
+    var csend chan<- int = c
+    var crecv <-chan int = c
+    close(c)     // legal
+    close(csend) // legal
+    close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed.  The compiler will
+now reject such code.
+</p>
+
 <h3 id="literals">Composite literals</h3>
 
 <h3 id="init">Goroutines during init</h3>
 
+<p>
+Go 1 allows goroutines to be created and run during initialization.
+(They used to be created but were not run until after initialization
+completed.) Code that uses goroutines can now be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}}
+-->var PackageGlobal int
+
+func init() {
+    c := make(chan int)
+    go initializationFunction(c)
+    PackageGlobal = &lt;-c
+}
+</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
 <h3 id="rune">The rune type</h3>
 
 <h3 id="delete">Deleting from maps</h3>
@@ -77,14 +152,161 @@ the ignored value can be safely discarded from the program and
 will flag other uses of the syntax for inspection by the programmer.
 </p>
 
-<h3 id="map_iteration">Iterating in maps</h3>
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/Sunday/` `/^  }/`}}
+-->    m := map[string]int{&#34;Sunday&#34;: 0, &#34;Monday&#34;: 1}
+    for name, value := range m {
+        // This loop should not assume Sunday will be visited first.
+        f(name, value)
+    }
+</pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help.  Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
 
 <h3 id="multiple_assignment">Multiple assignment</h3>
 
+<p>
+Go 1 fully specifies the evaluation order in multiple assignment
+statements. In particular, if the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value.  Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+-->    sa := []int{1, 2, 3}
+    i := 0
+    i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
+
+    sb := []int{1, 2, 3}
+    j := 0
+    sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
+
+    sc := []int{1, 2, 3}
+    sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
+</pre>
+
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
 <h3 id="shadowing">Returns and shadowed variables</h3>
 
+<p>
+A shadowed variable is one that has the same name as another variable in an inner scope.
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+    func Bug() (i, j, k int) {
+        for i = 0; i < 5; i++ {
+            for j := 0; j < 5; j++ { // Redeclares j.
+                k += i*j
+                if k > 100 {
+                    return // Rejected: j is shadowed here.
+                }
+            }
+        }
+        return // OK: j is not shadowed here.
+    }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
 <h3 id="equality">Equality of structs and arrays</h3>
 
+<p>
+Go 1 defines equality and inequality (<code>==</code> and
+<code>!=</code>) for struct and array values, respectively, provided
+the elements of the data structures can themselves be compared.
+That is, if equality is defined for all the fields of a struct (or
+an array element), then it is defined for the struct (or array).
+</p>
+
+<p>
+As a result, structs and arrays can now be used as map keys:
+</p>
+
+<pre><!--{{code "progs/go1.go" `/type Day struct/` `/Printf/`}}
+-->    //    type Day struct {
+    //        long string
+    //        short string
+    //    }
+    //    Christmas := Day{&#34;Christmas&#34;, &#34;XMas&#34;}
+    //    Thanksgiving := Day{&#34;Thanksgiving&#34;, &#34;Turkey&#34;}
+    //    holiday := map[Day]bool {
+    //        Christmas: true,
+    //        Thanksgiving: true,
+    //    }
+    //    fmt.Printf(&#34;Christmas is a holiday: %t\n&#34;, holiday[Christmas])
+</pre>
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible.  Also note that the ordered
+comparison operators (<code>&lt;</code> <code>&lt;=</code>
+<code>&gt;</code> <code>&gt;=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="funcs">Function and map equality</h3>
+
+<p>
+Go 1 disallows checking for equality of functions and maps,
+respectively, except to compare them directly to <code>nil</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
 <h2 id="library">Changes to the library</h2>
 
 <h3 id="hierarchy">The package hierarchy</h3>
@@ -106,7 +328,7 @@ while <a href="#deleted">others</a> have been deleted outright.
 <th align="left">Old path</th>
 <th align="left">New path</th>
 </tr>
-<tr><td>asn1 <td>encoding/asn1
+<tr><td>asn1</td> <td>encoding/asn1</td></tr>
 <tr><td>csv</td> <td>encoding/csv</td></tr>
 <tr><td>gob</td> <td>encoding/gob</td></tr>
 <tr><td>json</td> <td>encoding/json</td></tr>
index 3da62f8a3b6de10c735f1815431fc1c03a86eedf..d317f3b0f0b7d8653971e1e024be055ff055c3c3 100644 (file)
@@ -27,17 +27,79 @@ r60 to compile and run under Go 1. Finally, it outlines the new
 <code>go</code> command for building Go programs and the new binary
 release process being introduced. Most of these topics have more
 thorough presentations elsewhere; such documents are linked below.
+</p>
 
 <h2 id="language">Changes to the language</h2>
 
 <h3 id="append">Append</h3>
 
+<p>
+The <code>append</code> built-in function is variadic, so one can
+append to a byte slice using the <code>...</code> syntax in the
+call.
+</p>
+
+{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice; the conversion is no longer necessary:
+</p>
+
+{{code "progs/go1.go" `/append.*world/`}}
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
 <h3 id="close">Close</h3>
 
+<p>
+The <code>close</code> built-in function lets a sender tell a receiver
+that no more data will be transmitted on the channel.  In Go 1 the
+type system enforces the directionality when possible: it is illegal
+to call <code>close</code> on a receive-only channel:
+</p>
+
+<pre>
+    var c chan int
+    var csend chan<- int = c
+    var crecv <-chan int = c
+    close(c)     // legal
+    close(csend) // legal
+    close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed.  The compiler will
+now reject such code.
+</p>
+
 <h3 id="literals">Composite literals</h3>
 
 <h3 id="init">Goroutines during init</h3>
 
+<p>
+Go 1 allows goroutines to be created and run during initialization.
+(They used to be created but were not run until after initialization
+completed.) Code that uses goroutines can now be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}}
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
 <h3 id="rune">The rune type</h3>
 
 <h3 id="delete">Deleting from maps</h3>
@@ -71,14 +133,132 @@ the ignored value can be safely discarded from the program and
 will flag other uses of the syntax for inspection by the programmer.
 </p>
 
-<h3 id="map_iteration">Iterating in maps</h3>
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+{{code "progs/go1.go" `/Sunday/` `/^   }/`}}
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help.  Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
 
 <h3 id="multiple_assignment">Multiple assignment</h3>
 
+<p>
+Go 1 fully specifies the evaluation order in multiple assignment
+statements. In particular, if the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value.  Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
 <h3 id="shadowing">Returns and shadowed variables</h3>
 
+<p>
+A shadowed variable is one that has the same name as another variable in an inner scope.
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+    func Bug() (i, j, k int) {
+        for i = 0; i < 5; i++ {
+            for j := 0; j < 5; j++ { // Redeclares j.
+                k += i*j
+                if k > 100 {
+                    return // Rejected: j is shadowed here.
+                }
+            }
+        }
+        return // OK: j is not shadowed here.
+    }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
 <h3 id="equality">Equality of structs and arrays</h3>
 
+<p>
+Go 1 defines equality and inequality (<code>==</code> and
+<code>!=</code>) for struct and array values, respectively, provided
+the elements of the data structures can themselves be compared.
+That is, if equality is defined for all the fields of a struct (or
+an array element), then it is defined for the struct (or array).
+</p>
+
+<p>
+As a result, structs and arrays can now be used as map keys:
+</p>
+
+{{code "progs/go1.go" `/type Day struct/` `/Printf/`}}
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible.  Also note that the ordered
+comparison operators (<code>&lt;</code> <code>&lt;=</code>
+<code>&gt;</code> <code>&gt;=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="funcs">Function and map equality</h3>
+
+<p>
+Go 1 disallows checking for equality of functions and maps,
+respectively, except to compare them directly to <code>nil</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
 <h2 id="library">Changes to the library</h2>
 
 <h3 id="hierarchy">The package hierarchy</h3>
index 0a7416c48410f6ea6252bd2e0335408ee4c3fa80..f02ede740350e4dcb01503d5693ac25f840dd4ae 100644 (file)
@@ -9,7 +9,11 @@ package main
 import "log"
 
 func main() {
+       stringAppend()
        mapDelete()
+       mapIteration()
+       multipleAssignment()
+       structEquality()
 }
 
 func mapDelete() {
@@ -20,3 +24,73 @@ func mapDelete() {
                log.Fatal("mapDelete:", m)
        }
 }
+
+func stringAppend() {
+       greeting := []byte{}
+       greeting = append(greeting, []byte("hello ")...)
+       greeting = append(greeting, "world"...)
+       if string(greeting) != "hello world" {
+               log.Fatal("stringAppend: ", string(greeting))
+       }
+}
+
+func mapIteration() {
+       m := map[string]int{"Sunday": 0, "Monday": 1}
+       for name, value := range m {
+               // This loop should not assume Sunday will be visited first.
+               f(name, value)
+       }
+}
+
+func assert(t bool) {
+       if !t {
+               log.Panic("assertion fail")
+       }
+}
+
+func multipleAssignment() {
+       sa := []int{1, 2, 3}
+       i := 0
+       i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
+
+       sb := []int{1, 2, 3}
+       j := 0
+       sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
+
+       sc := []int{1, 2, 3}
+       sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
+
+       assert(i == 1 && sa[0] == 2)
+       assert(j == 1 && sb[0] == 2)
+       assert(sc[0] == 2)
+}
+
+func structEquality() {
+       // Feature not net in repo.
+       //      type Day struct {
+       //              long string
+       //              short string
+       //      }
+       //      Christmas := Day{"Christmas", "XMas"}
+       //      Thanksgiving := Day{"Thanksgiving", "Turkey"}
+       //      holiday := map[Day]bool {
+       //              Christmas: true,
+       //              Thanksgiving: true,
+       //      }
+       //      fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
+}
+
+func f(string, int) {
+}
+
+func initializationFunction(c chan int) {
+       c <- 1
+}
+
+var PackageGlobal int
+
+func init() {
+       c := make(chan int)
+       go initializationFunction(c)
+       PackageGlobal = <-c
+}