The declaration statement has the form
<p>
<pre>
- var s string = "";
+ var s string = ""
</pre>
<p>
This is the <code>var</code> keyword, followed by the name of the variable, followed by
We could write
<p>
<pre>
- var s = "";
+ var s = ""
</pre>
<p>
or we could go even shorter and write the idiom
<p>
<pre>
- s := "";
+ s := ""
</pre>
<p>
The <code>:=</code> operator is used a lot in Go to represent an initializing declaration.
a <code>string</code> value:
<p>
<pre>
- s[0] = 'x';
- (*p)[1] = 'y';
+ s[0] = 'x'
+ (*p)[1] = 'y'
</pre>
<p>
In C++ terms, Go strings are a bit like <code>const strings</code>, while pointers
Arrays are declared like this:
<p>
<pre>
- var arrayOfInt [10]int;
+ var arrayOfInt [10]int
</pre>
<p>
Arrays, like strings, are values, but they are mutable. This differs
elements for you, use <code>...</code> as the array size:
<p>
<pre>
- s := sum(&[...]int{1,2,3});
+ s := sum(&[...]int{1,2,3})
</pre>
<p>
In practice, though, unless you're meticulous about storage layout within a
<code>&</code>—is all you need:
<p>
<pre>
- s := sum([]int{1,2,3});
+ s := sum([]int{1,2,3})
</pre>
<p>
There are also maps, which you can initialize like this:
<p>
<pre>
type T struct { a, b int }
- var t *T = new(T);
+ var t *T = new(T)
</pre>
<p>
or the more idiomatic
<p>
<pre>
- t := new(T);
+ t := new(T)
</pre>
<p>
Some types—maps, slices, and channels (see below)—have reference semantics.
types you want to use the built-in function <code>make()</code>:
<p>
<pre>
- m := make(map[string]int);
+ m := make(map[string]int)
</pre>
<p>
This statement initializes a new map ready to store entries.
If you just declare the map, as in
<p>
<pre>
- var m map[string]int;
+ var m map[string]int
</pre>
<p>
it creates a <code>nil</code> reference that cannot hold anything. To use the map,
object. We could write
<p>
<pre>
- n := new(File);
- n.fd = fd;
- n.name = name;
+ n := new(File)
+ n.fd = fd
+ n.name = name
return n
</pre>
<p>
11 )
<p>
13 func main() {
-14 hello := []byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}
+14 hello := []byte("hello, world\n")
15 file.Stdout.Write(hello)
16 file, err := file.Open("/does/not/exist", 0, 0)
17 if file == nil {
14 a := sort.IntArray(data)
15 sort.Sort(a)
16 if !sort.IsSorted(a) {
-17 panic()
+17 panic("fail")
18 }
19 }
</pre>
</pre>
<p>
<pre>
- s, ok := v.(Stringer); // Test whether v implements "String()"
+ s, ok := v.(Stringer) // Test whether v implements "String()"
if ok {
result = s.String()
} else {
<p>
<pre>
type Writer interface {
- Write(p []byte) (n int, err os.Error);
+ Write(p []byte) (n int, err os.Error)
}
</pre>
<p>
computation but in the same address space:
<p>
<pre>
- go sum(hugeArray); // calculate sum in the background
+ go sum(hugeArray) // calculate sum in the background
</pre>
<p>
If you want to know when the calculation is done, pass a channel
on which it can report back:
<p>
<pre>
- ch := make(chan int);
- go sum(hugeArray, ch);
+ ch := make(chan int)
+ go sum(hugeArray, ch)
// ... do something else for a while
- result := <-ch; // wait for, and retrieve, result
+ result := <-ch // wait for, and retrieve, result
</pre>
<p>
Back to our prime sieve. Here's how the sieve pipeline is stitched
The declaration statement has the form
- var s string = "";
+ var s string = ""
This is the "var" keyword, followed by the name of the variable, followed by
its type, followed by an equals sign and an initial value for the variable.
string constant is of type string, we don't have to tell the compiler that.
We could write
- var s = "";
+ var s = ""
or we could go even shorter and write the idiom
- s := "";
+ s := ""
The ":=" operator is used a lot in Go to represent an initializing declaration.
There's one in the "for" clause on the next line:
However the following statements are illegal because they would modify
a "string" value:
- s[0] = 'x';
- (*p)[1] = 'y';
+ s[0] = 'x'
+ (*p)[1] = 'y'
In C++ terms, Go strings are a bit like "const strings", while pointers
to strings are analogous to "const string" references.
Arrays are declared like this:
- var arrayOfInt [10]int;
+ var arrayOfInt [10]int
Arrays, like strings, are values, but they are mutable. This differs
from C, in which "arrayOfInt" would be usable as a pointer to "int".
If you are creating a regular array but want the compiler to count the
elements for you, use "..." as the array size:
- s := sum(&[...]int{1,2,3});
+ s := sum(&[...]int{1,2,3})
In practice, though, unless you're meticulous about storage layout within a
data structure, a slice itself—using empty brackets and no
"&"—is all you need:
- s := sum([]int{1,2,3});
+ s := sum([]int{1,2,3})
There are also maps, which you can initialize like this:
returns a pointer to the allocated storage.
type T struct { a, b int }
- var t *T = new(T);
+ var t *T = new(T)
or the more idiomatic
- t := new(T);
+ t := new(T)
Some types—maps, slices, and channels (see below)—have reference semantics.
If you're holding a slice or a map and you modify its contents, other variables
referencing the same underlying data will see the modification. For these three
types you want to use the built-in function "make()":
- m := make(map[string]int);
+ m := make(map[string]int)
This statement initializes a new map ready to store entries.
If you just declare the map, as in
- var m map[string]int;
+ var m map[string]int
it creates a "nil" reference that cannot hold anything. To use the map,
you must first initialize the reference using "make()" or by assignment from an
the ones used to build maps and arrays, to construct a new heap-allocated
object. We could write
- n := new(File);
- n.fd = fd;
- n.name = name;
+ n := new(File)
+ n.fd = fd
+ n.name = name
return n
but for simple structures like "File" it's easier to return the address of a nonce
String() string
}
- s, ok := v.(Stringer); // Test whether v implements "String()"
+ s, ok := v.(Stringer) // Test whether v implements "String()"
if ok {
result = s.String()
} else {
interface type defined in the "io" library:
type Writer interface {
- Write(p []byte) (n int, err os.Error);
+ Write(p []byte) (n int, err os.Error)
}
(This interface is another conventional name, this time for "Write"; there are also
this starts the function running in parallel with the current
computation but in the same address space:
- go sum(hugeArray); // calculate sum in the background
+ go sum(hugeArray) // calculate sum in the background
If you want to know when the calculation is done, pass a channel
on which it can report back:
- ch := make(chan int);
- go sum(hugeArray, ch);
+ ch := make(chan int)
+ go sum(hugeArray, ch)
// ... do something else for a while
- result := <-ch; // wait for, and retrieve, result
+ result := <-ch // wait for, and retrieve, result
Back to our prime sieve. Here's how the sieve pipeline is stitched
together: