| # Proposal: Go 2 transition |
| |
| Author: Ian Lance Taylor |
| |
| Last update: October 15, 2018 |
| |
| ## Abstract |
| |
| A proposal for how to make incompatible changes from Go 1 to Go 2 |
| while breaking as little as possible. |
| |
| ## Background |
| |
| Currently the Go language and standard libraries are covered by the |
| [Go 1 compatibility guarantee](https://golang.org/doc/go1compat). |
| The goal of that document was to promise that new releases of Go would |
| not break existing working programs. |
| |
| Among the goals for the Go 2 process is to consider changes to the |
| language and standard libraries that will break the guarantee. |
| Since Go is used in a distributed open source environment, we cannot |
| rely on a [flag |
| day](http://www.catb.org/jargon/html/F/flag-day.html). |
| We must permit the interoperation of different packages written using |
| different versions of Go. |
| |
| Every language goes through version transitions. |
| As background, here are some notes on what other languages have done. |
| Feel free to skip the rest of this section. |
| |
| ### C |
| |
| C language versions are driven by the ISO standardization process. |
| C language development has paid close attention to backward |
| compatibility. |
| After the first ISO standard, C90, every subsequent standard has |
| maintained strict backward compatibility. |
| Where new keywords have been introduced, they are introduced in a |
| namespace reserved by C90 (an underscore followed by an uppercase |
| ASCII letter) and are made more accessible via a `#define` macro in a |
| header file that did not previously exist (examples are `_Complex`, |
| defined as `complex` in `<complex.h>`, and `_Bool`, defined as `bool` |
| in `<stdbool.h>`). |
| None of the basic language semantics defined in C90 have changed. |
| |
| In addition, most C compilers provide options to define precisely |
| which version of the C standard the code should be compiled for (for |
| example, `-std=c90`). |
| Most standard library implementations support feature macros that may |
| be #define’d before including the header files to specify exactly |
| which version of the library should be provided (for example, |
| `_ISOC99_SOURCE`). |
| While these features have had bugs, they are fairly reliable and are |
| widely used. |
| |
| A key feature of these options is that code compiled at different |
| language/library versions can in general all be linked together and |
| work as expected. |
| |
| The first standard, C90, did introduce breaking changes to the |
| previous C language implementations, known informally as K&R C. |
| New keywords were introduced, such as `volatile` (actually that might |
| have been the only new keyword in C90). |
| The precise implementation of integer promotion in integer expressions |
| changed from unsigned-preserving to value-preserving. |
| Fortunately it was easy to detect code using the new keywords due to |
| compilation errors, and easy to adjust that code. |
| The change in integer promotion actually made it less surprising to |
| naive users, and experienced users mostly used explicit casts to |
| ensure portability among systems with different integer sizes, so |
| while there was no automatic detection of problems not much code broke |
| in practice. |
| |
| There were also some irritating changes. |
| C90 introduced trigraphs, which changed the behavior of some string |
| constants. |
| Compilers adapted with options like -no-trigraphs and -Wtrigraphs. |
| |
| More seriously, C90 introduced the notion of undefined behavior, and |
| declared that programs that invoked undefined behavior might take |
| any action. |
| In K&R C, the cases that C90 described as undefined behavior were |
| mostly treated as what C90 called implementation-defined behavior: the |
| program would take some non-portable but predictable action. |
| Compiler writers absorbed the notion of undefined behavior, and |
| started writing optimizations that assumed that the behavior would not |
| occur. |
| This caused effects that surprised people not fluent in the C |
| standard. |
| I won’t go into the details here, but one example of this (from my |
| blog) is [signed overflow](http://www.airs.com/blog/archives/120). |
| |
| C of course continues to be the preferred language for kernel |
| development and the glue language of the computing industry. |
| Though it has been partially replaced by newer languages, this is not |
| because of any choices made by new versions of C. |
| |
| The lessons I see here are: |
| |
| * Backward compatibility matters. |
| * Breaking compatibility in small ways is OK, as long as people can |
| spot the breakages through compiler options or compiler errors. |
| * Compiler options to select specific language/library versions are |
| useful, provided code compiled using different options can be linked |
| together. |
| * Unlimited undefined behavior is confusing for users. |
| |
| ### C++ |
| |
| C++ language versions are also now driven by the ISO standardization process. |
| Like C, C++ pays close attention to backward compatibility. |
| C++ has been historically more free with adding new keywords (there |
| are 10 new keywords in C++11). |
| This works out OK because the newer keywords tend to be relatively |
| long (`constexpr`, `nullptr`, `static_assert`) and compilation errors |
| make it easy to find code using the new keywords as identifiers. |
| |
| C++ uses the same sorts of options for specifying the standard version |
| for language and libraries as are found in C. |
| It suffers from the same sorts of problems as C with regard to |
| undefined behavior. |
| |
| An example of a breaking change in C++ was the change in the scope of |
| a variable declared in the initialization statement of a for loop. |
| In the pre-standard versions of C++, the scope of the variable |
| extended to the end of the enclosing block, as though it were declared |
| immediately before the for loop. |
| During the development of the first C++ standard, C++98, this was |
| changed so that the scope was only within the for loop itself. |
| Compilers adapted by introducing options like `-ffor-scope` so that |
| users could control the expected scope of the variable (for a period |
| of time, when compiling with neither `-ffor-scope` nor |
| `-fno-for-scope`, the GCC compiler used the old scope but warned about |
| any code that relied on it). |
| |
| Despite the relatively strong backward compatibility, code written in |
| new versions of C++, like C++11, tends to have a very different feel |
| than code written in older versions of C++. |
| This is because styles have changed to use new language and library |
| features. |
| Raw pointers are less commonly used, range loops are used rather than |
| standard iterator patterns, new concepts like rvalue references and |
| move semantics are used widely, and so forth. |
| People familiar with older versions of C++ can struggle to understand |
| code written in new versions. |
| |
| C++ is of course an enormously popular language, and the ongoing |
| language revision process has not harmed its popularity. |
| |
| Besides the lessons from C, I would add: |
| |
| * A new version may have a very different feel while remaining |
| backward compatible. |
| |
| ### Java |
| |
| I know less about Java than about the other languages I discuss, so |
| there may be more errors here and there are certainly more biases. |
| |
| Java is largely backward compatible at the byte-code level, meaning |
| that Java version N+1 libraries can call code written in, and |
| compiled by, Java version N (and N-1, N-2, and so forth). |
| Java source code is also mostly backward compatible, although they do |
| add new keywords from time to time. |
| |
| The Java documentation is very detailed about potential compatibility |
| issues when moving from one release to another. |
| |
| The Java standard library is enormous, and new packages are added at |
| each new release. |
| Packages are also deprecated from time to time. |
| Using a deprecated package will cause a warning at compile time (the |
| warning may be turned off), and after a few releases the deprecated |
| package will be removed (at least in theory). |
| |
| Java does not seem to have many backward compatibility problems. |
| The problems are centered on the JVM: an older JVM generally will not |
| run newer releases, so you have to make sure that your JVM is at least |
| as new as that required by the newest library you want to use. |
| |
| Java arguably has something of a forward compatibility problem in |
| that JVM bytecodes present a higher level interface than that of a |
| CPU, and that makes it harder to introduce new features that cannot |
| be directly represented using the existing bytecodes. |
| |
| This forward compatibility problem is part of the reason that Java |
| generics use type erasure. |
| Changing the definition of existing bytecodes would have broken |
| existing programs that had already been compiled into bytecode. |
| Extending bytecodes to support generic types would have required a |
| large number of additional bytecodes to be defined. |
| |
| This forward compatibility problem, to the extent that it is a |
| problem, does not exist for Go. |
| Since Go compiles to machine code, and implements all required run |
| time checks by generating additional machine code, there is no similar |
| forward compatibility issue. |
| |
| But, in general: |
| |
| * Be aware of how compatibility issues may restrict future changes. |
| |
| ### Python |
| |
| Python 3.0 (also known as Python 3000) started development in 2006 and |
| was initially released in 2008. |
| In 2018 the transition is still incomplete. |
| Some people continue to use Python 2.7 (released in 2010). |
| This is not a path we want to emulate for Go 2. |
| |
| The main reason for this slow transition appears to be lack of |
| backward compatibility. |
| Python 3.0 was intentionally incompatible with earlier versions of |
| Python. |
| Notably, `print` was changed from a statement to a function, and |
| strings were changed to use Unicode. |
| Python is often used in conjunction with C code, and the latter change |
| meant that any code that passed strings from Python to C required |
| tweaking the C code. |
| |
| Because Python is an interpreted language, and because there is no |
| backward compatibility, it is impossible to mix Python 2 and Python |
| 3 code in the same program. |
| This means that for a typical program that uses a range of libraries, |
| each of those libraries must be converted to Python 3 before the |
| program can be converted. |
| Since programs are in various states of conversion, libraries must |
| support Python 2 and 3 simultaneously. |
| |
| Python supports statements of the form `from __future__ import |
| FEATURE`. |
| A statement like this changes the interpretation of the rest of the |
| file in some way. |
| For example, `from __future__ import print_function` changes `print` |
| from a statement (as in Python 2) to a function (as in Python 3). |
| This can be used to take incremental steps toward new language |
| versions, and to make it easier to share the same code among different |
| language versions. |
| |
| So, we knew it already, but: |
| |
| * Backward compatibility is essential. |
| * Compatibility of the interface to other languages is important. |
| * Upgrading to a new version is limited by the version that your |
| libraries support. |
| |
| ### Perl |
| |
| The Perl 6 development process began in 2000. |
| The first stable version of the Perl 6 spec was announced in 2015. |
| This is not a path we want to emulate for Go 2. |
| |
| There are many reasons for this slow path. |
| Perl 6 was intentionally not backward compatible: it was meant to fix |
| warts in the language. |
| Perl 6 was intended to be represented by a spec rather than, as with |
| previous versions of Perl, an implementation. |
| Perl 6 started with a set of change proposals, but then continued to |
| evolve over time, and then evolve some more. |
| |
| Perl supports `use feature` which is similar to Python's `from |
| __future__ import`. |
| It changes the interpretation of the rest of the file to use a |
| specified new language feature. |
| |
| * Don’t be Perl 6. |
| * Set and meet deadlines. |
| * Don’t change everything at once. |
| |
| ## Proposal |
| |
| ### Language changes |
| |
| Pedantically speaking, we must have a way to speak about specific |
| language versions. |
| Each change to the Go language first appears in a Go release. |
| We will use Go release numbers to define language versions. |
| That is the only reasonable choice, but it can be confusing because |
| standard library changes are also associated with Go release numbers. |
| When thinking about compatibility, it will be necessary to |
| conceptually separate the Go language version from the standard |
| library version. |
| |
| As an example of a specific change, type aliases were first available |
| in Go language version 1.9. |
| Type aliases were an example of a backward compatible language change. |
| All code written in Go language versions 1.0 through 1.8 continued to |
| work the same way with Go language 1.9. |
| Code using type aliases requires Go language 1.9 or later. |
| |
| #### Language additions |
| |
| Type aliases are an example of an addition to the language. |
| Code using the type alias syntax `type A = B` did not compile with Go |
| versions before 1.9. |
| |
| Type aliases, and other backward compatible changes since Go 1.0, show |
| us that for additions to the language it is not necessary for packages |
| to explicitly declare the minimum language version that they require. |
| Some packages changed to use type aliases. |
| When such a package was compiled with Go 1.8 tools, the package failed |
| to compile. |
| The package author can simply say: upgrade to Go 1.9, or downgrade to |
| an earlier version of the package. |
| None of the Go tools need to know about this requirement; it's implied |
| by the failure to compile with older versions of the tools. |
| |
| It's true of course that programmers need to understand language |
| additions, but the the tooling does not. |
| Neither the Go 1.8 tools nor the Go 1.9 tools need to explicitly know |
| that type aliases were added in Go 1.9, other than in the limited |
| sense that the Go 1.9 compiler will compile type aliases and the Go |
| 1.8 compiler will not. |
| That said, the possibility of specifying a minimum language version to |
| get better error messages for unsupported language features is |
| discussed below. |
| |
| #### Language removals |
| |
| We must also consider language changes that simply remove features |
| from the language. |
| For example, [issue 3939](http://golang.org/issue/3939) proposes that |
| we remove the conversion `string(i)` for an integer value `i`. |
| If we make this change in, say, Go version 1.20, then packages that |
| use this syntax will stop compiling in Go 1.20. |
| (If you prefer to restrict backward incompatible changes to new major |
| versions, then replace 1.20 by 2.0 in this discussion; the problem |
| remains the same.) |
| |
| In this case, packages using the old syntax have no simple recourse. |
| While we can provide tooling to convert pre-1.20 code into working |
| 1.20 code, we can't force package authors to run those tools. |
| Some packages may be unmaintained but still useful. |
| Some organizations may want to upgrade to 1.20 without having to |
| requalify the versions of packages that they rely on. |
| Some package authors may want to use 1.20 even though their packages |
| now break, but do not have time to modify their package. |
| |
| These scenarios suggest that we need a mechanism to specify the |
| maximum version of the Go language with which a package can be built. |
| |
| Importantly, specifying the maximum version of the Go language should |
| not be taken to imply the maximum version of the Go tools. |
| The Go compiler released with Go version 1.20 must be able to build |
| packages using Go language 1.19. |
| This can be done by adding an option to cmd/compile (and, if |
| necessary, cmd/asm and cmd/link) along the lines of the `-std` option |
| supported by C compilers. |
| When cmd/compile sees the option, perhaps `-lang=go1.19`, it will |
| compile the code using the Go 1.19 syntax. |
| |
| This requires cmd/compile to support all previous versions, one way or |
| another. |
| If supporting old syntaxes proves to be troublesome, the `-lang` |
| option could perhaps be implemented by passing the code through a |
| convertor from the old version to the current. |
| That would keep support of old versions out of cmd/compile proper, and |
| the convertor could be useful for people who want to update their |
| code. |
| But it is unlikely that supporting old language versions will be a |
| significant problem. |
| |
| Naturally, even though the package is built with the language version |
| 1.19 syntax, it must in other respects be a 1.20 package: it must link |
| with 1.20 code, be able to call and be called by 1.20 code, and so |
| forth. |
| |
| The go tool will need to know the maximum language version so that it |
| knows how to invoke cmd/compile. |
| Assuming we continue with the modules experiment, the logical place |
| for this information is the go.mod file. |
| The go.mod file for a module M can specify the maximum language |
| version for the packages that it defines. |
| This would be honored when M is downloaded as a dependency by some |
| other module. |
| |
| The maximum language version is not a minimum language version. |
| If a module require features in language 1.19, but can be built with |
| 1.20, we can say that the maximum language version is 1.20. |
| If we build with Go release 1.19, we will see that we are at less than |
| the maximum, and simply build with language version 1.19. |
| Maximum language versions greater than that supported by the current |
| tools can simply be ignored. |
| If we later build with Go release 1.21, we will build the module with |
| `-lang=go1.20`. |
| |
| This means that the tools can set the maximum language version |
| automatically. |
| When we use Go release 1.30 to release a module, we can mark the |
| module as having maximum language version 1.30. |
| All users of the module will see this maximum version and do the right |
| thing. |
| |
| This implies that we will have to support old versions of the language |
| indefinitely. |
| If we remove a language feature after version 1.25, version 1.26 and |
| all later versions will still have to support that feature if invoked |
| with the `-lang=go1.25` option (or `-lang=go1.24` or any other earlier |
| version in which the feature is supported). |
| Of course, if no `-lang` option is used, or if the option is |
| `-lang=go1.26` or later, the feature will not be available. |
| Since we do not expect wholesale removals of existing language |
| features, this should be a manageable burden. |
| |
| I believe that this approach suffices for language removals. |
| |
| #### Minimum language version |
| |
| For better error messages it may be useful to permit the module file |
| to specify a minimum language version. |
| This is not required: if a module uses features introduced in |
| language version 1.N, then building it with 1.N-1 will fail at compile |
| time. |
| This may be confusing, but in practice it will likely be obvious what |
| the problem is. |
| |
| That said, if modules can specify a minimum language version, the go |
| tool could produce an immediate, clear error message when building |
| with 1.N-1. |
| |
| The minimum language version could potentially be set by the compiler |
| or some other tool. |
| When compiling each file, see which features it uses, and use that to |
| determine the minimum version. |
| It need not be precisely accurate. |
| |
| This is just a suggestion, not a requirement. |
| It would likely provide a better user experience as the language |
| changes. |
| |
| #### Language redefinitions |
| |
| The Go language can also change in ways that are not additions or |
| removals, but are instead changes to the way a specific language |
| construct works. |
| For example, in Go 1.1 the size of the type `int` on 64-bit hosts |
| changed from 32 bits to 64 bits. |
| This change was relatively harmless, as the language does not specify |
| the exact size of `int`. |
| Potentially, though, some Go 1.0 programs continued to compile with Go |
| 1.1 but stopped working. |
| |
| A redefinition is a case where we have code that compiles successfully |
| with both versions 1.N and version 1.M, where M > N, and where the |
| meaning of the code is different in the two versions. |
| For example, [issue 20733](https://golang.org/issue/20733) proposes |
| that variables in a range loop should be redefined in each iteration. |
| Though in practice this change seems more likely to fix programs than |
| to break them, in principle this change might break working programs. |
| |
| Note that a new keyword normally cannot cause a redefinition, though |
| we must be careful to ensure that that is true before introducing |
| one. |
| For example, if we introduce the keyword `check` as suggested in [the |
| error handling draft |
| design](https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md), |
| and we permit code like `check(f())`, that might seem to be a |
| redefinition if `check` is defined as a function in the same package. |
| But after the keyword is introduced, any attempt to define such a |
| function will fail. |
| So it is not possible for code using `check`, under whichever meaning, |
| to compile with both version 1.N and 1.M. |
| The new keyword can be handled as a removal (of the non-keyword use of |
| `check`) and an addition (of the keyword `check`). |
| |
| In order for the Go ecosystem to survive a transition to Go 2, we must |
| minimize these sorts of redefinitions. |
| As discussed earlier, successful languages have generally had |
| essentially no redefinitions beyond a certain point. |
| |
| The complexity of a redefinition is, of course, that we can no longer |
| rely on the compiler to detect the problem. |
| When looking at a redefined language construct, the compiler cannot |
| know which meaning is meant. |
| In the presence of redefined language constructs, we cannot determine |
| the maximum language version. |
| We don't know if the construct is intended to be compiled with the old |
| meaning or the new. |
| |
| The only possibility would be to let programmers set the language |
| version. |
| In this case it would be either a minimum or maximum language |
| version, as appropriate. |
| It would have to be set in such a way that it would not be |
| automatically updated by any tools. |
| Of course, setting such a version would be error prone. |
| Over time, a maximum language version would lead to surprising |
| results, as people tried to use new language features, and failed. |
| |
| I think the only feasible safe approach is to not permit language |
| redefinitions. |
| |
| We are stuck with our current semantics. |
| This doesn't mean we can't improve them. |
| For example, for [issue 20733](https://golang.org/issue/20733), the |
| range issue, we could change range loops so that taking the address of |
| a range parameter, or referring to it from a function literal, is |
| forbidden. |
| This would not be a redefinition; it would be a removal. |
| That approach might eliminate the bugs without the potential of |
| breaking code unexpectedly. |
| |
| #### Build tags |
| |
| Build tags are an existing mechanism that can be used by programs to |
| choose which files to compile based on the release. |
| |
| Build tags name release versions, which look just like language |
| versions, but, speaking pedantically, are different. |
| In the discussion above we've talked about using Go release 1.N to |
| compile code with language version 1.N-1. |
| That is not possible using build tags. |
| |
| Build tags can be used to set the maximum or a minimum release, or |
| both, that will be used to compile a specific file. |
| They can be a convenient way to take advantage of language changes |
| that are only available after a certain version; that is, they can be |
| used to set a minimum language version when compiling a file. |
| |
| As discussed above, though, what is most useful for language changes |
| is the ability to set a maximum language version. |
| Build tags don't provide that in a useful way. |
| If you use a build tag to set your current release version as your |
| maximum version, your package will not build with later releases. |
| Setting a maximum language version is only possible when it is set to |
| a version before the current release, and is coupled with an alternate |
| implementation that is used for the later versions. |
| That is, if you are building with 1.N, it's not helpful to use a build |
| tag of `!1.N+1`. |
| You could use a build tag of `!1.M` where `M < N`, but in almost all |
| cases you will then need a separate file with a build tag of `1.M+1`. |
| |
| Build tags can be used to handle language redefinitions: if there is a |
| language redefinition at language version `1.N`, programmers can write |
| one file with a build tag of `!1.N` using the old semantics and a |
| different file with a build tag of `1.N` using the new semantics. |
| However, these duplicate implementations are a lot of work, it's hard |
| to know in general when it is required, and it would be easy to make a |
| mistake. |
| The availability of build tags is not enough to overcome the earlier |
| comments about not permitting any language redefinitions. |
| |
| #### import "go2" |
| |
| It would be possible to add a mechanism to Go similar to Python's |
| `from __future__ import` and Perl's `use feature`. |
| For example, we could use a special import path, such as `import |
| "go2/type-aliases"`. |
| This would put the required language features in the file that uses |
| them, rather than hidden away in the go.mod file. |
| |
| This would provide a way to describe the set of language additions |
| required by the file. |
| It's more complicated, because instead of relying on a language |
| version, the language is broken up into separate features. |
| There is no obvious way to ever remove any of these special imports, |
| so they will tend to accumulate over time. |
| Python and Perl avoid the accumulation problem by intentionally making |
| a backward incompatible change. |
| After moving to Python 3 or Perl 6, the accumulated feature requests |
| can be discarded. |
| Since Go is trying to avoid a large backward incompatible change, |
| there would be no clear way to ever remove these imports. |
| |
| This mechanism does not address language removals. |
| We could introduce a removal import, such as `import |
| "go2/no-int-to-string"`, but it's not obvious why anyone would ever |
| use it. |
| In practice, there would be no way to ever remove language features, |
| even ones that are confusing and error-prone. |
| |
| This kind of approach doesn't seem suitable for Go. |
| |
| ### Standard library changes |
| |
| One of the benefits of a Go 2 transition is the chance to release some |
| of the standard library packages from the Go 1 compatibility |
| guarantee. |
| Another benefit is the chance to move many, perhaps most, of the |
| packages out of the six month release cycle. |
| If the modules experiment works out it may even be possible to start |
| doing this sooner rather than later, with some packages on a faster |
| cycle. |
| |
| I propose that the six month release cycle continue, but that it be |
| treated as a compiler/runtime release cycle. |
| We want Go releases to be useful out of the box, so releases will |
| continue to include the current versions of roughly the same set of |
| packages that they contain today. |
| However, many of those packages will actually be run on their own |
| release cycles. |
| People using a given Go release will be able to explicitly choose to |
| use newer versions of the standard library packages. |
| In fact, in some cases they may be able to use older versions of the |
| standard library packages where that seems useful. |
| |
| Different release cycles would require more resources on the part of |
| the package maintainers. |
| We can only do this if we have enough people to manage it and enough |
| testing resources to test it. |
| |
| We could also continue using the six month release cycle for |
| everything, but make the separable packages available separately for |
| use with different, compatible, releases. |
| |
| #### Core standard library |
| |
| Still, some parts of the standard library must be treated as core |
| libraries. |
| These libraries are closely tied to the compiler and other tools, and |
| must strictly follow the release cycle. |
| Neither older nor newer versions of these libraries may be used. |
| |
| Ideally, these libraries will remain on the current version 1. |
| If it seems necessary to change any of them to version 2, that will |
| have to be discussed on a case by case basis. |
| At this time I see no reason for it. |
| |
| The tentative list of core libraries is: |
| |
| * os/signal |
| * plugin |
| * reflect |
| * runtime |
| * runtime/cgo |
| * runtime/debug |
| * runtime/msan |
| * runtime/pprof |
| * runtime/race |
| * runtime/tsan |
| * sync |
| * sync/atomic |
| * testing |
| * time |
| * unsafe |
| |
| I am, perhaps optimistically, omitting the net, os, and syscall |
| packages from this list. |
| We'll see what we can manage. |
| |
| #### Penumbra standard library |
| |
| The penumbra standard library consists of those packages that are |
| included with a release but are maintained independently. |
| This will be most of the current standard library. |
| These packages will follow the same discipline as today, with the |
| option to move to a v2 where appropriate. |
| It will be possible to use `go get` to upgrade or, possibly, downgrade |
| these standard library packages. |
| In particular, fixes can be made as minor releases separately from the |
| six month core library release cycle. |
| |
| The go tool will have to be able to distinguish between the core |
| library and the penumbra library. |
| I don't know precisely how this will work, but it seems feasible. |
| |
| When moving a standard library package to v2, it will be essential to |
| plan for programs that use both v1 and v2 of the package. |
| Those programs will have to work as expected, or if that is impossible |
| will have to fail cleanly and quickly. |
| In some cases this will involve modifying the v1 version to use an |
| internal package that is also shared by the v2 package. |
| |
| Standard library packages will have to compile with older versions of |
| the language, at least the two previous release cycles that we |
| currently support. |
| |
| #### Removing packages from the standard library |
| |
| The ability to support `go get` of standard library packages will |
| permit us to remove packages from the releases. |
| Those packages will continue to exist and be maintained, and people |
| will be able to retrieve them if they need them. |
| However, they will not be shipped by default with a Go release. |
| |
| This will include packages like |
| |
| * index/suffixarray |
| * log/syslog |
| * net/http/cgi |
| * net/http/fcgi |
| |
| and perhaps other packages that do not seem to be widely useful. |
| |
| We should in due course plan a deprecation policy for old packages, to |
| move these packages to a point where they are no longer maintained. |
| The deprecation policy will also apply to the v1 versions of packages |
| that move to v2. |
| |
| Or this may prove to be too problematic, and we should never deprecate |
| any existing package, and never remove them from the standard |
| releases. |
| |
| ## Go 2 |
| |
| If the above process works as planned, then in an important sense |
| there never will be a Go 2. |
| Or, to put it a different way, we will slowly transition to new |
| language and library features. |
| We could at any point during the transition decide that now we are |
| Go 2, which might be good marketing. |
| Or we could just skip it (there has never been a C 2.0, why have a Go |
| 2.0?). |
| |
| Popular languages like C, C++, and Java never have a version 2. |
| In effect, they are always at version 1.N, although they use different |
| names for that state. |
| I believe that we should emulate them. |
| In truth, a Go 2 in the full sense of the word, in the sense of an |
| incompatible new version of the language or core libraries, would not |
| be a good option for our users. |
| A real Go 2 would, perhaps unsurprisingly, be harmful. |