The Go Programming Language This chapter contains language-specific recommendations for Go.
Memory safety Go provides memory safety, but only if the program is not executed in parallel (that is, GOMAXPROCS is not larger than 1). The reason is that interface values and slices consist of multiple words are not updated atomically. Another thread of execution can observe an inconsistent pairing between type information and stored value (for interfaces) or pointer and length (for slices), and such inconsistency can lead to a memory safety violation. Code which does not run in parallel and does not use the unsafe package (or other packages which expose unsafe constructs) is memory-safe. For example, invalid casts and out-of-range subscripting cause panics at run time. Keep in mind that finalization can introduce parallelism because finalizers are executed concurrently, potentially interleaved with the rest of the program.
Error handling Only a few common operations (such as pointer dereference, integer division, array subscripting) trigger exceptions in Go, called panics. Most interfaces in the standard library use a separate return value of type error to signal error. Not checking error return values can lead to incorrect operation and data loss (especially in the case of writes, using interfaces such as io.Writer). The correct way to check error return values depends on the function or method being called. In the majority of cases, the first step after calling a function should be an error check against the nil value, handling any encountered error. See for details. Regular error handling in Go However, with io.Reader, io.ReaderAt and related interfaces, it is necessary to check for a non-zero number of read bytes first, as shown in . If this pattern is not followed, data loss may occur. This is due to the fact that the io.Reader interface permits returning both data and an error at the same time. Read error handling in Go
Garbage Collector Older Go releases (before Go 1.3) use a conservative garbage collector without blacklisting. This means that data blobs can cause retention of unrelated data structures because the data is conservatively interpreted as pointers. This phenomenon can be triggered accidentally on 32-bit architectures and is more likely to occur if the heap grows larger. On 64-bit architectures, it may be possible to trigger it deliberately—it is unlikely to occur spontaneously.
Marshaling and unmarshaling Several packages in the encoding hierarchy provide support for serialization and deserialization. The usual caveats apply (see ). As an additional precaution, the Unmarshal and Decode functions should only be used with fresh values in the interface{} argument. This is due to the way defaults for missing values are implemented: During deserialization, missing value do not result in an error, but the original value is preserved. Using a fresh value (with suitable default values if necessary) ensures that data from a previous deserialization operation does not leak into the current one. This is especially relevant when structs are deserialized.