Everything in Go is passed by value. A function always gets a copy of the thing being passed, as if there were an assignment statement assigning the value to the parameter. For instance, copying a pointer value makes a copy of the pointer, not the data it points to.
Map and slice values behave like pointers; they are descriptors that contain pointers to the underlying map or slice data. Copying a map or slice value doesn't copy the data it points to. Copying an interface value makes a copy of the thing stored in the interface value. If the interface value holds a struct, copying the interface value makes a copy of the struct. If the interface value holds a pointer, copying the interface value makes a copy of the pointer, but again not the data it points to.
func (s *MyStruct) someMethod() { } // method on pointer func (s MyStruct) someMethod() { } // method on value
When defining a method on a type, the receiver (s
in the above
example) behaves exactly is if it were an argument to the method. Define the
method on a pointer type if you need the method to modify the data the receiver
points to. Otherwise, it is often cleaner to define the method on a value type.
In short: new
allocates memory, make
initializes
the slice, map, and channel types.
See the relevant section of Effective Go for more details.
int
32 bits on 64 bit machines?
The size of int
and float
is implementation-specific.
The 64 bit Go compilers (both 6g and gccgo) use a 32 bit representation for
both int
and float
. Code that relies on a particular
size of value should use an explicitly sized type, like int64
or
float64
.
We haven't fully defined it all yet, but some details about atomicity are available in the Go Memory Model specification. Also, some concurrency questions are answered in more detail in the language design FAQ.
Regarding mutexes, the sync package implements them, but we hope Go programming style will encourage people to try higher-level techniques. In particular, consider structuring your program so that only one goroutine at a time is ever responsible for a particular piece of data.
Do not communicate by sharing memory. Instead, share memory by communicating.
Under the gc compilers you must set GOMAXPROCS
to allow the
runtime to utilise more than one OS thread. Under gccgo
an OS
thread will be created for each goroutine, and GOMAXPROCS
is
effectively equal to the number of running goroutines.
Programs that perform concurrent computation should benefit from an increase in
GOMAXPROCS
. (See the runtime package
documentation.)
GOMAXPROCS
> 1 sometimes make my program
slower?(This is specific to the gc compilers. See above.)
It depends on the nature of your program. Programs that contain several goroutines that spend a lot of time communicating on channels will experience performance degradation when using multiple OS threads. This is because of the significant context-switching penalty involved in sending data between threads.
The Go runtime's scheduler is not as good as it needs to be. In future, it
should recognise such cases and optimize its use of OS threads. For now,
GOMAXPROCS
should be set on a per-application basis.
Some confusion may arise when using closures with concurrency. Consider the following program:
func main() { done := make(chan bool) values = []string{ "a", "b", "c" } for _, v := range values { go func() { fmt.Println(v) done <- true }() } // wait for all goroutines to complete before exiting for i := range values { <-done } }
One might mistakenly expect to see a, b, c
as the output.
What you'll probably see instead is c, c, c
. This is because
each closure shares the same variable v
. Each closure prints the
value of v
at the time fmt.Println
is executed,
rather than the value of v
when the goroutine was launched.
To bind the value of v
to each closure as they are launched, one
could modify the inner loop to read:
for _, v := range values { go func(u) { fmt.Println(u) done <- true }(v) }
In this example, the value of v
is passed as an argument to the
anonymous function. That value is then accessible inside the function as
the variable u
.
?:
operator?There is no ternary form in Go. You may use the following to achieve the same result:
if expr { n = trueVal } else { n = falseVal }
Put all the source files for the package in a directory by themselves. Source files can refer to items from different files at will; there is no need for forward declarations or a header file.
Other than being split into multiple files, the package will compile and test just like a single-file package.
Create a new file ending in _test.go
in the same directory
as your package sources. Inside that file, import "testing"
and write functions of the form
func TestFoo(t *testing.T) { ... }
Run gotest
in that directory.
That script finds the Test
functions,
builds a test binary, and runs it.
In Go, you must specify a 2-dimensional array literal like this:
var intArray = [4][4]int{ [4]int{1, 2, 3, 4}, [4]int{2, 4, 8, 16}, [4]int{3, 9, 27, 81}, [4]int{4, 16, 64, 256}, }
It seems that the [4]int
could be inferred, but in general it's
hard to get this sort of thing right.
Some of Go's designers had worked on other languages that derived types automatically in such expressions, but the special cases that arise can be messy, especially when interfaces, nil, constant conversions, and such are involved. It seemed better to require the full type information. That way there will be no surprises.