Go version 1

We want to be able to provide a stable base for people using Go.  People should be able to write Go programs and expect that they will continue to compile and run without change, on a timescale of years.  Similarly, people should be able to write books about Go, be able to say which version of Go the book is describing, and have that version number still be meaningful much later.  None of these properties are true for Go today.

We propose to issue a Go release early next year that will be called “Go version 1”, Go 1 for short, that will be the first Go release to be stable in this way.  Code that compiles in Go version 1 should, with few exceptions, continue to compile throughout the lifetime of that version, as we issue updates and bug fixes such as Go version 1.1, 1.2, and so on. It will also be maintained with fixes for bugs and security flaws even as other versions may evolve. Also, production environments such as Google App Engine will support it for an extended time.

Go version 1 will be a stable language with stable libraries. Other than critical fixes, changes made to the library and packages for versions 1.1, 1.2 and so on may add functionality but will not break existing Go version 1 programs.

Our goal is for Go 1 to be a stable version of today’s Go, not a wholesale rethinking of the language.  In particular, we are explicitly resisting any efforts to design new language features “by committee.”

However, there are various changes to the Go language and packages that we have intended for some time and prototyped but not done primarily because they are significant and backwards-incompatible. If Go 1 is to be long-lasting, it is important that we plan, announce, implement, and test these changes as part of the preparation of Go 1, rather than delay them until after it is released and thereby introduce divergence that contradicts our goals.

This document outlines the changes that are planned for Go 1.  The details of any particular change are beyond the scope of this document.  We are focused here on backwards-incompatible changes, because those are the ones that must be planned for and that would, if delayed until after Go 1, shorten Go 1’s longevity. A few compatible changes are also included because they have significant consequences.

Despite this long list, the changes are all modest in linguistic scope, although some of the renamings have wide reach.

We are publishing this preliminary plan for Go 1 for feedback from the Go community.  If you have feedback, please reply to the thread on the golang-nuts mailing list.

Language

append (in weekly.2011-10-18)

Append does not provide a way to append a string to a []byte.

Go 1 will allow append(b, s...) where b is []byte and s is a string.

close (in weekly.2011-10-18)

Close is intended as a way for a sender to signal that no more values will be sent.  

Go 1 will disallow close on receive-only channels.

composite literals (in weekly.2011-12-06)

Today, a composite literal of the form T{...} initializing a value of type T can be abbreviated by omitting the T.  There is no abbreviation for &T{...} initializing a *T.

        type Entry struct {

                Name string

                Value float64

        }

        

        // valid today: unabbreviated slice elements of type Entry

        var dict4 = []Entry{

                Entry{“pi”, 3.14},

                Entry{“e”, 2.72},

        }

        // valid today: abbreviated slice elements of type Entry

        var dict5 = []Entry{

                {“pi”, 3.14},

{“e”, 2.72},

}

Go 1 will allow abbreviating a composite literal of the form &T{...} initializing a value of type *T, by omitting the &T.

        // valid today: unabbreviated slice elements of type *Entry

        var dict6 = []*Entry{

                &Entry{“pi”, 3.14},

                &Entry{“e”, 2.72},

        }

        // not valid today, but valid in Go 1: abbreviated slice elements of type *Entry

        var dict7 = []*Entry{

                {“pi”, 3.14},

                {“e”, 2.72},

        }

There will be no gofix module for this change: all current composite literals will continue to be valid.

error type (in weekly.2011-11-02)

Go 1 will introduce a new predefined type error, defined as if by

        type error interface {

                Error() string

        }

The discussion of os.Error in the packages section below has more details.

goroutines during init (in weekly.2011-10-25)

The current language defines that “go” statements executed during init create goroutines that do not begin to run until initialization of the entire program is complete.

To be determined: Go 1 may relax this restriction.  As an experiment we plan to remove the restriction entirely and then restore it if it creates terrible problems.

int/rune (in weekly.2011-10-26)

The language spec allows the int type to be 32 or 64 bits wide, but current implementations set int to 32 bits even on 64-bit platforms.  It would be preferable to have int be 64 bits on 64-bit platforms. (There are important consequences for indexing large slices.) However, this change would waste space when processing Unicode characters because the int type is used to hold Unicode code points: each code point would waste an extra 32 bits of storage.

The resolution is to introduce a new type for Unicode characters, called rune.

Go 1 will define "rune" as a type alias for "int32", analogous to byte as a type alias for uint8.  The standard packages will use rune for Unicode code points.  Using int32 instead of int makes it reasonable to change int to be 64 bits later.

Code that uses “int” or “[]int” to hold runes will typically need to be updated to say “rune” or “[]rune”.  The compiler will point these out as type errors.  There is no gofix module.

map deletion (in weekly.2011-10-18)

The “m[x] = ignored, false” map assignment syntax is a special case (the only 1=2 assignment), requires passing a value (ignored) that is evaluated but discarded, and requires passing a value that is nearly always a constant (the value false).

Go 1 will remove the special map assignment and introduce a new built-in function, delete: delete(m, x) will delete the map entry retrieved by the expression m[x].  Deleting a non-existent entry is a no-op.  The function has no return value.

Gofix will convert “m[x] = ignored, false” into “delete(m, x)” when it is clear that the ignored value can be safely discarded from the program and false refers to the predefined boolean constant.  It will flag other uses of the syntax for inspection by the programmer.

map iteration (in weekly.2011-10-18)

The language leaves map iteration order undefined and in practice it differs across hardware platforms.

Go 1 will define that map iteration order may change even from one iteration to the next.  This allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.

multiple assignment (in weekly.2011-10-18)

The current specification of multiple assignment guarantees that the right-hand-side expressions are all evaluated before any left-hand-side expressions are assigned: “The expressions on the right are evaluated before assigning to any of the operands on the left, but otherwise the evaluation order is unspecified....”  It says nothing, though, about the order of assignment.

Go 1 will fully specify multiple assignment. The expressions on the right and any sub-expressions on the left will be evaluated before assigning to any of the operands on the left.  The assignments on the left will then proceed in left-to-right order.

Thus:

        m := []int{1, 2, 3}

        i := 0

        i, m[i] = 1, 2  // sets i = 1, m[0] = 2

        i = 0

        m[i], i = 2, 1  // sets m[0] = 2, i = 1

        m[0], m[0] = 1, 2  // sets m[0] = 1, then m[0] = 2 (so m[0] = 2 at end)

return and := shadowing (in weekly.2011-10-18)

A common mistake is to use “return” (without arguments) after an assignment to a variable that has the same name as a result variable but is not the result variable. This situation is called shadowing: the result variable has been shadowed by the other variable.

Go 1’s compilers will reject a return statement without arguments when any of the result variables has been shadowed.  This rule will not be defined in the language spec, by analogy with the rules about when a function is missing a return statement. Not specifying the behavior, while enforcing with the compilers, makes it easier to adjust the rules as we continue to explore this area of the Go language.

equality

The current language does not define equality on struct and array values.  It does define equality on function and map values.  Function equality is problematic in some contexts and map equality compares pointers, not the maps’ content.  Only types with defined equality can be used as map keys.

Go 1 will define equality on struct and array values composed from fields on which equality is also defined (element-wise comparison).  It will remove equality on function and map values except for comparison with nil.

Go 1 will continue to exclude equality for slices. (In the general case deep equality is infeasible.)

copying values with unexported fields (in weekly.2011-11-18)

The current language does not allow a package to make a copy of a struct value containing unexported fields belonging to a different package.  There is, however, a required exception for a method receiver, and the implementations of copy and append have never honored this restriction.  


Go 1 will allow packages to copy struct values containing unexported fields from other packages.  This admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface.  time.Time and reflect.Value are examples of types taking advantage of this.

Existing code will continue to run.  However, code that depends heavily on other packages not making copies should think about replacing the fields with an unexported pointer to those fields, or perhaps switching to use of an interface value.  The implementation of os.File is an example of the pointer approach.

Packages

rearrangement (revised; in weekly.2011-11-09)

The package hierarchy has grown organically and could use some pruning and cultivation.

Go 1 will include some rearrangement of the package hierarchy. Some pieces will move into subrepositories of code.google.com/p/go; others will be moved to other parts of the standard repository.

moving to encoding/*:

        asn1

        csv

        gob

        json

        xml

moving to html/*:

        exp/template/html (renamed to html/template)

moving to math/*:

        big

        cmath (renamed to math/cmplx)

        rand

        

moving to net/*:

        http

        mail

        rpc

        smtp

        url

moving to os/*:

        exec

moving to text/*:

        scanner

        tabwriter

        template

moving to unicode/*:
        utf8

        utf16

moving to exp/* (and thus not in Go 1):

        ebnf, command ebnflint

        go/types, command gotype

        http/spdy

to be deleted:

        container/vector

        exp/datafmt

        go/typechecker

        try, command gotry

exp/* - not in Go 1

The exp/ package hierarchy holds experimental code and will not be part of Go 1, nor probably part of any future Go release. Code in exp/ is ours to change as we like, without worrying about breaking users. That's what the directory is for.

Before Go version 1, we expect exp/norm and exp/template/html to move out of exp, to unicode/norm and a location still to be decided.

old/* - not in Go 1

The old/ package hierarchy, which holds deprecated code, will also not be part of Go 1. In the future we might use old/ for retired packages to ease transitions.  For example, if Go 2 retires Go 1’s package foo, Go 2 might still include it as old/foo, and then Go 3 would remove it entirely.  There are no such packages today.

crypto/openpgp, websocket - not in Go 1, moved to subrepositories of code.google.com/p/go

Code that is not of general utility (such as crypto/openpgp) or that is expected to need to change significantly over short time scales (such as websocket) will be moved to external repositories.  As part of that effort we plan to set up a separate dashboard for repositories showing the build and test status against different Go versions.   We also plan to set up subrepositories in the code.google.com/p/go project for code maintained as part of the Go project, to include additional crypto code, perhaps websocket, and perhaps also packages for graphics and protocol buffers.

Gofix will handle updating import paths to point at the new repositories.  If it beomes necessary to change the Google Code import syntax from “crypto.go.googlecode.com/hg/openpgp” to “code.google.com/p/go.crypto/openpgp”,  gofix will handle that change too.

html

The html package needs to be finalized with respect to its API and some of the implementation details. If this cannot be done in time, the package should move to exp.  Moving html to exp does not preclude having an html/template package.

netchan - not in Go 1, move to old/netchan (in weekly.2011-10-18)

The netchan package is an experiment but needs to be redone.  It is not ready for production use and may need significant API revisions, so we will move it into the old/ tree before the Go 1 release.  We will develop a new netchan in exp/netchan.

os - replace os.Error with predefined error type (in weekly.2011-11-02)

The placement of os.Error in package os is mostly historical: errors first came up when implementing package os, and they seemed fundamental at the time.  Since then it has become clear that errors are more fundamental than the operating system.  For example, it would be nice to use Errors in packages that os depends on, like syscall.  Also, having Error in os introduces many dependencies on os that would otherwise not exist.

Go 1 will have a built-in type “error” defined as if by “type error interface { Error() string }” and a separate package errors (analogous to bytes and strings) that contains utility functions.  os.NewError will be replaced by errors.New.  As part of this change, os.EOF will move to io.EOF, os.Errno to syscall.Errno, and uses of operating system errors (for example, the uses of os.EINVAL and os.ERANGE by package strconv) will be discouraged.

Gofix handles most code affected by this change.

os - make FileInfo an interface, add FileMode (in weekly.2011-12-01)

To allow file system-like interfaces to file trees other than those provided by the operating system, Go 1 will change os.FileInfo from a struct to an interface with at least these methods:

        type FileInfo interface {

                Name() string

                Size() int64

                Mode() FileMode

                ModTime() time.Nano

                Sys() interface{}

        }

The current os.FileInfo’s Mode field is defined by package syscall, which makes it unportable.

Go 1 will define a new, portable type FileMode with fixed bit values.

It may be necessary to move the FileInfo and FileMode types into package io.

Gofix handles much of the code affected by this change.

syscall - use error, define Errno (in weekly.2011-12-01)

The syscall package, which predates os.Error, returns errors as “int” values.

Go 1’s package syscall will return values of type error for errors.  On Unix, syscall will define a syscall.Errno type that replaces os.Errno.

Gofix handles nearly all code affected by this change.

time - define Time, and Duration types (in weekly.2011-12-01)

The time package uses int64 to represent instants in time, in units of both seconds and nanoseconds since 1970, as well as for nanosecond-based durations.

Go 1’s package time will define one type, Time, for times, and another type, Duration, for durations measured in nanoseconds.

Gofix can help with converting expressions - time.Nanoseconds() becomes time.Now(), for instance - but the code will still be broken after gofix.  It will be up to programmers to make their programs use the right types, which will require careful thought.

Tools

The Go 1 release will be available in source and binary form for at least these platforms:

        FreeBSD 7+: amd64, 386

        Linux 2.6+: amd64, 386, arm

        OS X (Snow Leopard + Lion): amd64, 386

        Windows (2000 + later): amd64, 386

Programmers won’t need a C compiler to compile their Go code, nor will they need an Xcode download on Apple machinery. (Those who wish to work on the standard repository will still need these tools, however.)

The Go 1 release will include a new tool “go” that will replace both goinstall and make.

The two compiler suites - gc and gccgo - will be at even parity for Go 1.  For gccgo, this means implementing goroutines and also support for cgo packages.