581 lines
20 KiB
HTML
581 lines
20 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<title>research!rsc: My Go Resolutions for 2017</title>
|
|||
|
<link rel="alternate" type="application/atom+xml" title="research!rsc - Atom" href="http://research.swtch.com/feed.atom" />
|
|||
|
|
|||
|
<link href='https://fonts.googleapis.com/css?family=Inconsolata:400,700' rel='stylesheet' type='text/css'>
|
|||
|
<script type="text/javascript" src="https://use.typekit.com/skm6yij.js"></script>
|
|||
|
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
|||
|
<style>
|
|||
|
body {
|
|||
|
padding: 0;
|
|||
|
margin: 0;
|
|||
|
font-size: 100%;
|
|||
|
}
|
|||
|
.header {
|
|||
|
height: 1.25em;
|
|||
|
background-color: #dff;
|
|||
|
margin: 0;
|
|||
|
padding: 0.1em 0.1em 0.2em;
|
|||
|
border-top: 1px solid black;
|
|||
|
border-bottom: 1px solid #8ff;
|
|||
|
}
|
|||
|
.header h3 {
|
|||
|
margin: 0;
|
|||
|
padding: 0 2em;
|
|||
|
display: inline-block;
|
|||
|
padding-right: 2em;
|
|||
|
font-style: italic;
|
|||
|
font-family: "adobe-text-pro" !important;
|
|||
|
font-size: 90%;
|
|||
|
}
|
|||
|
.rss {
|
|||
|
float: right;
|
|||
|
padding-top: 0.2em;
|
|||
|
padding-right: 2em;
|
|||
|
display: none;
|
|||
|
}
|
|||
|
.toc {
|
|||
|
margin-top: 2em;
|
|||
|
}
|
|||
|
.toc-title {
|
|||
|
font-family: "caflisch-script-pro";
|
|||
|
font-size: 300%;
|
|||
|
line-height: 50%;
|
|||
|
}
|
|||
|
.toc-subtitle {
|
|||
|
display: block;
|
|||
|
margin-bottom: 1em;
|
|||
|
font-size: 83%;
|
|||
|
}
|
|||
|
@media only screen and (max-width: 550px) { .toc-subtitle { display: none; } }
|
|||
|
.header h3 a {
|
|||
|
color: black;
|
|||
|
}
|
|||
|
.header h4 {
|
|||
|
margin: 0;
|
|||
|
padding: 0;
|
|||
|
display: inline-block;
|
|||
|
font-weight: normal;
|
|||
|
font-size: 83%;
|
|||
|
}
|
|||
|
@media only screen and (max-width: 550px) { .header h4 { display: none; } }
|
|||
|
.main {
|
|||
|
padding: 0 2em;
|
|||
|
}
|
|||
|
@media only screen and (max-width: 479px) { .article { font-size: 120%; } }
|
|||
|
.article h1 {
|
|||
|
text-align: center;
|
|||
|
}
|
|||
|
.article h1, .article h2, .article h3 {
|
|||
|
font-family: 'Myriad Pro';
|
|||
|
}
|
|||
|
.normal {
|
|||
|
font-size: medium;
|
|||
|
font-weight: normal;
|
|||
|
}
|
|||
|
.when {
|
|||
|
text-align: center;
|
|||
|
font-size: 100%;
|
|||
|
margin: 0;
|
|||
|
padding: 0;
|
|||
|
}
|
|||
|
.when p {
|
|||
|
margin: 0;
|
|||
|
padding: 0;
|
|||
|
}
|
|||
|
.article h2 {
|
|||
|
font-size: 100%;
|
|||
|
padding-top: 0.25em;
|
|||
|
}
|
|||
|
pre {
|
|||
|
margin-left: 4em;
|
|||
|
margin-right: 4em;
|
|||
|
}
|
|||
|
pre, code {
|
|||
|
font-family: 'Inconsolata', monospace;
|
|||
|
font-size: 100%;
|
|||
|
}
|
|||
|
.footer {
|
|||
|
margin-top: 10px;
|
|||
|
font-size: 83%;
|
|||
|
font-family: sans-serif;
|
|||
|
}
|
|||
|
.comments {
|
|||
|
margin-top: 2em;
|
|||
|
background-color: #ffe;
|
|||
|
border-top: 1px solid #aa4;
|
|||
|
border-left: 1px solid #aa4;
|
|||
|
border-right: 1px solid #aa4;
|
|||
|
}
|
|||
|
.comments-header {
|
|||
|
padding: 0 5px 0 5px;
|
|||
|
}
|
|||
|
.comments-header p {
|
|||
|
padding: 0;
|
|||
|
margin: 3px 0 0 0;
|
|||
|
}
|
|||
|
.comments-body {
|
|||
|
padding: 5px 5px 5px 5px;
|
|||
|
}
|
|||
|
#plus-comments {
|
|||
|
border-bottom: 1px dotted #ccc;
|
|||
|
}
|
|||
|
.plus-comment {
|
|||
|
width: 100%;
|
|||
|
font-size: 14px;
|
|||
|
border-top: 1px dotted #ccc;
|
|||
|
}
|
|||
|
.me {
|
|||
|
background-color: #eec;
|
|||
|
}
|
|||
|
.plus-comment ul {
|
|||
|
margin: 0;
|
|||
|
padding: 0;
|
|||
|
list-style: none;
|
|||
|
width: 100%;
|
|||
|
display: inline-block;
|
|||
|
}
|
|||
|
.comment-when {
|
|||
|
color:#999;
|
|||
|
width:auto;
|
|||
|
padding:0 5px;
|
|||
|
}
|
|||
|
.old {
|
|||
|
font-size: 83%;
|
|||
|
}
|
|||
|
.plus-comment ul li {
|
|||
|
display: inline-block;
|
|||
|
vertical-align: top;
|
|||
|
margin-top: 5px;
|
|||
|
margin-bottom: 5px;
|
|||
|
padding: 0;
|
|||
|
}
|
|||
|
.plus-icon {
|
|||
|
width: 45px;
|
|||
|
}
|
|||
|
.plus-img {
|
|||
|
float: left;
|
|||
|
margin: 4px 4px 4px 4px;
|
|||
|
width: 32px;
|
|||
|
height: 32px;
|
|||
|
}
|
|||
|
.plus-comment p {
|
|||
|
margin: 0;
|
|||
|
padding: 0;
|
|||
|
}
|
|||
|
.plus-clear {
|
|||
|
clear: left;
|
|||
|
}
|
|||
|
.toc-when {
|
|||
|
font-size: 83%;
|
|||
|
color: #ccc;
|
|||
|
}
|
|||
|
.toc {
|
|||
|
list-style: none;
|
|||
|
}
|
|||
|
.toc li {
|
|||
|
margin-bottom: 0.5em;
|
|||
|
}
|
|||
|
.toc-head {
|
|||
|
margin-bottom: 1em !important;
|
|||
|
font-size: 117%;
|
|||
|
}
|
|||
|
.toc-summary {
|
|||
|
margin-left: 2em;
|
|||
|
}
|
|||
|
.favorite {
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
.article p {
|
|||
|
line-height: 144%;
|
|||
|
}
|
|||
|
sup, sub {
|
|||
|
vertical-align: baseline;
|
|||
|
position: relative;
|
|||
|
font-size: 83%;
|
|||
|
}
|
|||
|
sup {
|
|||
|
bottom: 1ex;
|
|||
|
}
|
|||
|
sub {
|
|||
|
top: 0.8ex;
|
|||
|
}
|
|||
|
|
|||
|
.main {
|
|||
|
position: relative;
|
|||
|
margin: 0 auto;
|
|||
|
padding: 0;
|
|||
|
width: 900px;
|
|||
|
}
|
|||
|
@media only screen and (min-width: 768px) and (max-width: 959px) { .main { width: 708px; } }
|
|||
|
@media only screen and (min-width: 640px) and (max-width: 767px) { .main { width: 580px; } }
|
|||
|
@media only screen and (min-width: 480px) and (max-width: 639px) { .main { width: 420px; } }
|
|||
|
@media only screen and (max-width: 479px) { .main { width: 300px; } }
|
|||
|
|
|||
|
</style>
|
|||
|
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
<div class="header">
|
|||
|
<h3><a href="/">research!rsc</a></h3>
|
|||
|
<h4>Thoughts and links about programming,
|
|||
|
by <a href="https://swtch.com/~rsc/" rel="author">Russ Cox</a> </h4>
|
|||
|
<a class="rss" href="/feed.atom"><img src="/feed-icon-14x14.png" /></a>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="main">
|
|||
|
<div class="article">
|
|||
|
<h1>My Go Resolutions for 2017
|
|||
|
<div class="normal">
|
|||
|
<div class="when">
|
|||
|
|
|||
|
Posted on Wednesday, January 18, 2017.
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</h1>
|
|||
|
<p class=lp>’Tis the season for resolutions,
|
|||
|
and I thought it would make sense to write a little
|
|||
|
about what I hope to work on this year as far as Go is concerned.</p>
|
|||
|
|
|||
|
<p class=pp>My goal every year is to <em>help Go developers</em>.
|
|||
|
I want to make sure that the work we do on the Go team
|
|||
|
has a significant, positive impact on Go developers.
|
|||
|
That may sound obvious, but there are a variety of common ways to fail to achieve that:
|
|||
|
for example, spending too much time cleaning up or optimizing code that doesn’t need it;
|
|||
|
responding only to the most common or recent complaints or requests;
|
|||
|
or focusing too much on short-term improvements.
|
|||
|
It’s important to step back and make sure we’re focusing
|
|||
|
our development work where it does the most good.</p>
|
|||
|
|
|||
|
<p class=pp>This post outlines a few of my own major focuses for this year.
|
|||
|
This is only my personal list, not the Go team’s list.</p>
|
|||
|
|
|||
|
<p class=pp>One reason for posting this is to gather feedback.
|
|||
|
If these spark any ideas or suggestions of your own,
|
|||
|
please feel free to comment below or on the linked GitHub issues.</p>
|
|||
|
|
|||
|
<p class=pp>Another reason is to make clear that I’m aware of these issues as important.
|
|||
|
I think too often people interpret lack of action by the Go team
|
|||
|
as a signal that we think everything is perfect, when instead
|
|||
|
there is simply other, higher priority work to do first.</p>
|
|||
|
|
|||
|
<h2><a name="alias"></a>Type aliases</h2>
|
|||
|
|
|||
|
<p class=lp>There is a recurring problem with moving types
|
|||
|
from one package to another during large codebase refactorings.
|
|||
|
We tried to solve it last year with <a href="https://golang.org/issue/16339">general aliases</a>,
|
|||
|
which didn’t work for at least two reasons: we didn’t explain the change well enough,
|
|||
|
and we didn’t deliver it on time, so it wasn’t ready for Go 1.8.
|
|||
|
Learning from that experience,
|
|||
|
I <a href="https://www.youtube.com/watch?v=h6Cw9iCDVcU">gave a talk</a>
|
|||
|
and <a href="https://talks.golang.org/2016/refactor.article">wrote an article</a>
|
|||
|
about the underlying problem,
|
|||
|
and that started a <a href="https://golang.org/issue/18130">productive discussion</a>
|
|||
|
on the Go issue tracker about the solution space.
|
|||
|
It looks like more limited <a href="https://golang.org/design/18130-type-alias">type aliases</a>
|
|||
|
are the right next step.
|
|||
|
I want to make sure those land smoothly in Go 1.9. <a href="https://golang.org/issue/18130">#18130</a>.</p>
|
|||
|
|
|||
|
<h2><a name="package"></a>Package management</h2>
|
|||
|
|
|||
|
<p class=lp>I designed the Go support for downloading published packages
|
|||
|
(“goinstall”, which became “go get”) in February 2010.
|
|||
|
A lot has happened since then.
|
|||
|
In particular, other language ecosystems have really raised the bar
|
|||
|
for what people expect from package management,
|
|||
|
and the open source world has mostly agreed on
|
|||
|
<a href="http://semver.org/">semantic versioning</a>, which provides a useful base
|
|||
|
for inferring version compatibility.
|
|||
|
Go needs to do better here, and a group of contributors have been
|
|||
|
<a href="https://blog.gopheracademy.com/advent-2016/saga-go-dependency-management/">working on a solution</a>.
|
|||
|
I want to make sure these ideas are integrated well
|
|||
|
into the standard Go toolchain and to make package management
|
|||
|
a reason that people love Go.</p>
|
|||
|
|
|||
|
<h2><a name="build"></a>Build improvements</h2>
|
|||
|
|
|||
|
<p class=lp>There are a handful of shortcomings in the design of
|
|||
|
the go command’s build system that are overdue to be fixed.
|
|||
|
Here are three representative examples that I intend to
|
|||
|
address with a bit of a redesign of the internals of the go command.</p>
|
|||
|
|
|||
|
<p class=pp>Builds can be too slow,
|
|||
|
because the go command doesn’t cache build results as aggressively as it should.
|
|||
|
Many people don’t realize that <code>go</code> <code>install</code> saves its work while <code>go</code> <code>build</code> does not,
|
|||
|
and then they run repeated <code>go</code> <code>build</code> commands that are slow
|
|||
|
because the later builds do more work than they should need to.
|
|||
|
The same for repeated <code>go</code> <code>test</code> without <code>go</code> <code>test</code> <code>-i</code> when dependencies are modified.
|
|||
|
All builds should be as incremental as possible.
|
|||
|
<a href="https://golang.org/issue/4719">#4719</a>.</p>
|
|||
|
|
|||
|
<p class=pp>Test results should be cached too:
|
|||
|
if none of the inputs to a test have changed,
|
|||
|
then usually there is no need to rerun the test.
|
|||
|
This will make it very cheap to run “all tests” when little or nothing has changed.
|
|||
|
<a href="https://golang.org/issue/11193">#11193</a>.</p>
|
|||
|
|
|||
|
<p class=pp>Work outside GOPATH should be supported nearly as well
|
|||
|
as work inside GOPATH.
|
|||
|
In particular, it should be possible to <code>git</code> <code>clone</code> a repo,
|
|||
|
<code>cd</code> into it, and run <code>go</code> commands and have them work fine.
|
|||
|
Package management only makes that more important:
|
|||
|
you’ll need to be able to work on different versions of a package (say, v1 and v2)
|
|||
|
without having entirely separate GOPATHs for them.
|
|||
|
<a href="https://golang.org/issue/17271">#17271</a>.</p>
|
|||
|
|
|||
|
<h2><a name="corpus"></a>Code corpus</h2>
|
|||
|
|
|||
|
<p class=lp>I think it helped to have concrete examples from real projects
|
|||
|
in the talk and article I prepared about codebase refactoring (see <a href="#alias">above</a>).
|
|||
|
We’ve also defined that <a href="https://golang.org/src/cmd/vet/README">additions to vet</a>
|
|||
|
must target problems that happen frequently in real programs.
|
|||
|
I’d like to see that kind of analysis of actual practice—examining
|
|||
|
the effects on and possible improvements to real programs—become a
|
|||
|
standard way we discuss and evaluate changes to Go.</p>
|
|||
|
|
|||
|
<p class=pp>Right now there’s not an agreed-upon representative corpus of code to use for
|
|||
|
those analyses: everyone must first create their own, which is too much work.
|
|||
|
I’d like to put together a single, self-contained Git repo people can check out that
|
|||
|
contains our official baseline corpus for those analyses.
|
|||
|
A possible starting point could be the top 100 Go language repos
|
|||
|
on GitHub by stars or forks or both.</p>
|
|||
|
|
|||
|
<h2><a name="vet"></a>Automatic vet</h2>
|
|||
|
|
|||
|
<p class=lp>The Go distribution ships with this powerful tool,
|
|||
|
<a href="https://golang.org/cmd/vet/"><code>go</code> <code>vet</code></a>,
|
|||
|
that points out correctness bugs.
|
|||
|
We have a high bar for checks, so that when vet speaks, you should listen.
|
|||
|
But everyone has to remember to run it.
|
|||
|
It would be better if you didn’t have to remember.
|
|||
|
In particular, I think we could probably run vet
|
|||
|
in parallel with the final compile and link of the test binary
|
|||
|
during <code>go</code> <code>test</code> without slowing the compile-edit-test cycle at all.
|
|||
|
If we can do that, and if we limit the enabled vet checks to a subset
|
|||
|
that is essentially 100% accurate,
|
|||
|
we can make passing vet a precondition for running a test at all.
|
|||
|
Then developers don’t need to remember to run <code>go</code> <code>vet</code>.
|
|||
|
They run <code>go</code> <code>test</code>,
|
|||
|
and once in a while vet speaks up with something important
|
|||
|
and avoids a debugging session.
|
|||
|
<a href="https://golang.org/issue/18084">#18084</a>,
|
|||
|
<a href="https://golang.org/issue/18085">#18085</a>.</p>
|
|||
|
|
|||
|
<h2><a name="error"></a>Errors & best practices</h2>
|
|||
|
|
|||
|
<p class=lp>Part of the intended contract for error reporting in Go is that functions
|
|||
|
include relevant available context, including the operation being attempted
|
|||
|
(such as the function name and its arguments).
|
|||
|
For example, this program:</p>
|
|||
|
|
|||
|
<pre><code>err := os.Remove("/tmp/nonexist")
|
|||
|
fmt.Println(err)
|
|||
|
</code></pre>
|
|||
|
|
|||
|
<p class=lp>prints this output:</p>
|
|||
|
|
|||
|
<pre><code>remove /tmp/nonexist: no such file or directory
|
|||
|
</code></pre>
|
|||
|
|
|||
|
<p class=lp>Not enough Go code adds context like <code>os.Remove</code> does. Too much code does only</p>
|
|||
|
|
|||
|
<pre><code>if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
</code></pre>
|
|||
|
|
|||
|
<p class=lp>all the way up the call stack,
|
|||
|
discarding useful context that should be reported
|
|||
|
(like <code>remove</code> <code>/tmp/nonexist:</code> above).
|
|||
|
I would like to try to understand whether our expectations
|
|||
|
for including context are wrong, or if there is something
|
|||
|
we can do to make it easier to write code that returns better errors.</p>
|
|||
|
|
|||
|
<p class=pp>There are also various discussions in the community about
|
|||
|
agreed-upon interfaces for stripping error context.
|
|||
|
I would like to try to understand when that makes sense and
|
|||
|
whether we should adopt an official recommendation.</p>
|
|||
|
|
|||
|
<h2><a name="context"></a>Context & best practices</h2>
|
|||
|
|
|||
|
<p class=lp>We added the new <a href="https://golang.org/pkg/context/">context package</a>
|
|||
|
in Go 1.7 for holding request-scoped information like
|
|||
|
<a href="https://blog.golang.org/context">timeouts, cancellation state, and credentials</a>.
|
|||
|
An individual context is immutable (like an individual string or int):
|
|||
|
it is only possible to derive a new, updated context and
|
|||
|
pass that context explicitly further down the call stack or
|
|||
|
(less commonly) back up to the caller.
|
|||
|
The context is now carried through APIs such as
|
|||
|
<a href="https://golang.org/pkg/database/sql">database/sql</a>
|
|||
|
and
|
|||
|
<a href="https://golang.org/pkg/net/http">net/http</a>,
|
|||
|
mainly so that those can stop processing a request when the caller
|
|||
|
is no longer interested in the result.
|
|||
|
Timeout information is appropriate to carry in a context,
|
|||
|
but—to use a <a href="https://golang.org/issue/18284">real example we removed</a>—database options
|
|||
|
are not, because they are unlikely to apply equally well to all possible
|
|||
|
database operations carried out during a request.
|
|||
|
What about the current clock source, or logging sink?
|
|||
|
Is either of those appropriate to store in a context?
|
|||
|
I would like to try to understand and characterize the
|
|||
|
criteria for what is and is not an appropriate use of context.</p>
|
|||
|
|
|||
|
<h2><a name="memory"></a>Memory model</h2>
|
|||
|
|
|||
|
<p class=lp>Go’s <a href="https://golang.org/ref/mem">memory model</a> is intentionally low-key,
|
|||
|
making few promises to users, compared to other languages.
|
|||
|
In fact it starts by discouraging people from reading the rest of the document.
|
|||
|
At the same time, it demands more of the compiler than other languages:
|
|||
|
in particular, a race on an integer value is not sufficient license
|
|||
|
for your program to misbehave in arbitrary ways.
|
|||
|
But there are some complete gaps, in particular no mention of
|
|||
|
the <a href="https://golang.org/pkg/sync/atomic/">sync/atomic package</a>.
|
|||
|
I think the core compiler and runtime developers all agree
|
|||
|
that the behavior of those atomics should be roughly the same as
|
|||
|
C++ seqcst atomics or Java volatiles,
|
|||
|
but we still need to write that down carefully in the memory model,
|
|||
|
and probably also in a long blog post.
|
|||
|
<a href="https://golang.org/issue/5045">#5045</a>,
|
|||
|
<a href="https://golang.org/issue/7948">#7948</a>,
|
|||
|
<a href="https://golang.org/issue/9442">#9442</a>.</p>
|
|||
|
|
|||
|
<h2><a name="immutability"></a>Immutability</h2>
|
|||
|
|
|||
|
<p class=lp>The <a href="https://golang.org/doc/articles/race_detector.html">race detector</a>
|
|||
|
is one of Go’s most loved features.
|
|||
|
But not having races would be even better.
|
|||
|
I would love it if there were some reasonable way to integrate
|
|||
|
<a href="https://www.google.com/search?q=%22reference+immutability%22">reference immutability</a> into Go,
|
|||
|
so that programmers can make clear, checked assertions about what can and cannot
|
|||
|
be written and thereby eliminate certain races at compile time.
|
|||
|
Go already has one immutable type, <code>string</code>; it would
|
|||
|
be nice to retroactively define that
|
|||
|
<code>string</code> is a named type (or type alias) for <code>immutable</code> <code>[]byte</code>.
|
|||
|
I don’t think that will happen this year,
|
|||
|
but I’d like to understand the solution space better.
|
|||
|
Javari, Midori, Pony, and Rust have all staked out interesting points
|
|||
|
in the solution space, and there are plenty of research papers
|
|||
|
beyond those.</p>
|
|||
|
|
|||
|
<p class=pp>In the long-term, if we could statically eliminate the possibility of races,
|
|||
|
that would eliminate the need for most of the memory model.
|
|||
|
That may well be an impossible dream,
|
|||
|
but again I’d like to understand the solution space better.</p>
|
|||
|
|
|||
|
<h2><a name="generics"></a>Generics</h2>
|
|||
|
|
|||
|
<p class=lp>Nothing sparks more <a href="https://research.swtch.com/dogma">heated arguments</a>
|
|||
|
among Go and non-Go developers than the question of whether Go should
|
|||
|
have support for generics (or how many years ago that should have happened).
|
|||
|
I don’t believe the Go team has ever said “Go does not need generics.”
|
|||
|
What we <em>have</em> said is that there are higher-priority issues facing Go.
|
|||
|
For example, I believe that better support for package management
|
|||
|
would have a much larger immediate positive impact on most Go developers
|
|||
|
than adding generics.
|
|||
|
But we do certainly understand that for a certain subset of Go use cases,
|
|||
|
the lack of parametric polymorphism is a significant hindrance.</p>
|
|||
|
|
|||
|
<p class=pp>Personally, I would like to be able to write general channel-processing
|
|||
|
functions like:</p>
|
|||
|
|
|||
|
<pre><code>// Join makes all messages received on the input channels
|
|||
|
// available for receiving from the returned channel.
|
|||
|
func Join(inputs ...<-chan T) <-chan T
|
|||
|
|
|||
|
// Dup duplicates messages received on c to both c1 and c2.
|
|||
|
func Dup(c <-chan T) (c1, c2 <-chan T)
|
|||
|
</code></pre>
|
|||
|
|
|||
|
<p class=lp>I would also like to be able to write
|
|||
|
Go support for high-level data processing abstractions,
|
|||
|
analogous to
|
|||
|
<a href="https://research.google.com/pubs/archive/35650.pdf">FlumeJava</a> or
|
|||
|
C#’s <a href="https://en.wikipedia.org/wiki/Language_Integrated_Query">LINQ</a>,
|
|||
|
in a way that catches type errors at compile time instead of at run time.
|
|||
|
There are also any number of data structures or generic algorithms
|
|||
|
that might be written,
|
|||
|
but I personally find these broader applications more compelling.</p>
|
|||
|
|
|||
|
<p class=pp>We’ve <a href="https://research.swtch.com/generic">struggled</a> off and on
|
|||
|
<a href="https://golang.org/design/15292-generics">for years</a>
|
|||
|
to find the right way to add generics to Go.
|
|||
|
At least a few of the past proposals got hung up on trying to design
|
|||
|
something that provided both general parametric polymorphism
|
|||
|
(like <code>chan</code> <code>T</code>) and also a unification of <code>string</code> and <code>[]byte</code>.
|
|||
|
If the latter is handled by parameterization over immutability,
|
|||
|
as described in the previous section, then maybe that simplifies
|
|||
|
the demands on a design for generics.</p>
|
|||
|
|
|||
|
<p class=pp>When I first started thinking about generics for Go in 2008,
|
|||
|
the main examples to learn from were C#, Java, Haskell, and ML.
|
|||
|
None of the approaches in those languages seemed like a
|
|||
|
perfect fit for Go.
|
|||
|
Today, there are newer attempts to learn from as well,
|
|||
|
including Dart, Midori, Rust, and Swift.</p>
|
|||
|
|
|||
|
<p class=pp>It’s been a few years since we ventured out and explored the design space.
|
|||
|
It is probably time to look around again,
|
|||
|
especially in light of the insight about mutability and
|
|||
|
the additional examples set by newer languages.
|
|||
|
I don’t think generics will happen this year,
|
|||
|
but I’d like to be able to say I understand the solution space better.</p>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<div id="disqus_thread"></div>
|
|||
|
<script>
|
|||
|
var disqus_config = function () {
|
|||
|
this.page.url = "https://research.swtch.com/go2017";
|
|||
|
this.page.identifier = "blog/go2017";
|
|||
|
};
|
|||
|
(function() {
|
|||
|
var d = document, s = d.createElement('script');
|
|||
|
s.src = '//swtch.disqus.com/embed.js';
|
|||
|
s.setAttribute('data-timestamp', +new Date());
|
|||
|
(d.head || d.body).appendChild(s);
|
|||
|
})();
|
|||
|
</script>
|
|||
|
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|||
|
</script>
|
|||
|
<script type="text/javascript">
|
|||
|
var pageTracker = _gat._getTracker("UA-3319603-2");
|
|||
|
pageTracker._initData();
|
|||
|
pageTracker._trackPageview();
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|