
Go Lang: Comments Are Not Directives - Merkur
Go 1.4 starts to use comments as directives. I think that is a realy bad path to go on the long run. You see its beginnings in following 3 examples:<p># used to set a canonical import path for a package:
&#x2F;&#x2F;import &quot;foo&quot;<p># used to generate code:
&#x2F;&#x2F;go:generate bar<p># used to document the result of a example function:
&#x2F;&#x2F;Output: foo<p>Comments should not be directives. Comments are free form, they do not have a syntax (as demonstrated in the examples). Comments are for humans - programms should ignore them or threat them as - comments!<p>It is my optinion that if Go needs some kind of annotation, than there should be a new syntax for it.<p>I would propose that directives to the tool chain will be marked with<p>#TAG: DIRECTIVE<p>a tool would be able to register the TAG with the go build environment. If a TAG is found in the code - the tool is called to do what ever needs to be done.
======
TheDong
Want to know what's even worse? Using comments for something _but not parsing
the syntax tree_.

In go 1.4, save the following to a file and run 'go generate' on it:
[https://play.golang.org/p/9WJtxClRXr](https://play.golang.org/p/9WJtxClRXr)
(I'd make it run in the playground, but you can't 'fork exec', so
exec.Command($GOBIN, generate) won't work sadly)

Even though that code has no comments (only a multi-line string), go generate
will run and print out a '\'.

I also used that generate command to point out that with generate, as it
exists in 1.4, there's actually NO WAY to print out a dollar sign.

The dollar-sign part of this is fixed in master (so go1.5), but it was fixed
not by allowing '\$', but by the bizarre $DOLLAR environment variable. See
[https://go-review.googlesource.com/#/c/8091/](https://go-
review.googlesource.com/#/c/8091/)

These "features" make the use of comments as directives even worse, because
it's _NOT_ comments being used as directives in the case of go generate, but
simple string matching. It literally just loops through lines of text and
checks if it startswith the correct substring.

This was, of course, done due to lazyness (same as $DOLLAR and many other
'features' of go), and the lazyness is starting to show through the cracks
here and there.

Go often prefers pain for the programmer for the compiler developer's life
being simpler by about 5 minutes.

~~~
eis
That's pretty bad.

I think the reason why people are so upset/surprised is because they expect
better from the Go team. Sometimes it really feels like they take the lazy
route without putting enough thought and polish into things. Which is
amplified by the previous statements regarding for example generics where they
said they wont introduce them until they find a really good way to do it but
then crank out half baked stuff like this.

~~~
coldtea
> _I think the reason why people are so upset /surprised is because they
> expect better from the Go team. Sometimes it really feels like they take the
> lazy route without putting enough thought and polish into things._

I think that was the case with Go from the start. Can you think of some aspect
that was especially well thought-out?

~~~
andrewchambers
Go has the best and most consistent std library I have seen.

~~~
TheDong
Consistent standard library?

It's a crapshoot what will be an interface and what will be a struct, which is
one of the fundamental features of the language.

Returned error values are sometimes errors.New (e.g. io.EOF) and sometimes
random fmt.Errorf strings that couldn't possibly be handled (e.g. all of
tls.go basically), sometimes actual structs (e.g. PathError), and sometimes
panics.

If you can't even get error handling right and consistent, what claim do you
have to consistency? At least in java it's pretty much all exceptions.

The math library, as mentioned above, is pretty darn iffy.

The existence of both 'path' and 'filepath' is possibly a mistake.

The 'heap' and 'list' in collections both seem like they should be similar,
but 'heap' operates on a thing that fulfills its interface and list operates
directly on arbitrary objects without some interface needed.

Due to the lack of 'protected', the std library is littered with exported
fields you shouldn't use (e.g. gob.CommonType and
template.Template.*parse.Tree and so on).

Sure, the library is consistent in many places because the language is so
small there's little else it can do but be consistent, but the fact that it
falls flat in error handling and has visible warts makes me feel that it's a
very broad std library, but far less consistent than, say, Rust's (where
everything returns consistent Optional error types) or Java's or Smalltalks.
Sure, it's more consistent than the clusterfuck that is ruby and/or python or
javascript or (heaven forbid) c/c++, but by no means is being better than any
of those an achievement in this category.

~~~
chimeracoder
> Returned error values are sometimes errors.New (e.g. io.EOF) and sometimes
> random fmt.Errorf strings that couldn't possibly be handled (e.g. all of
> tls.go basically), sometimes actual structs (e.g. PathError),

This is the advantage of having errors be interfaces rather than concrete
values. Once you learn how to use it, it's a strength. The usage of structs
that satisfy the interface (as in PathError) is clearly documented and
completely predictable. If your concern is that a certain package could use a
struct satisfying the interface and does not, well, one advantage of errors as
interfaces is that you could propose this change without breaking the
backwards compatibility guarantee.

It's really important to keep in mind that errors are adopted from error
values in C, which means that their idioms and usage is inspired by that
rather than by exception handling. Many new Go programmers (including me, when
I started) were more familiar with exception handling in higher-level
languages than error handling in idiomatic C, so it does take some getting
used to.

> and sometimes panics.

Do you have any examples of the standard library using panics to signal
handle-able errors ( _not_ counting cases in which the panic is recovered at
the top-level in the library and never visible to the caller)?

> The math library, as mentioned above, is pretty darn iffy.

The only complaint I have had about package "math" is that all operations are
defined on float64s, which can be annoying, but is far better than any
alternative. That's an annoyance, but it's certainly not an inconsistency in
the library.

Do you have any other examples of inconsistencies in the math package?

~~~
TheDong
No, the advantage of having an interface is everything can return an error I
can typeswitch on. Unfortunately, you can't (in a backwards compatible way)
change io.EOF or any of the other 'constant' errors because there's so much
code doing 'if err != io.EOF' which now breaks. In addition, it's backwards
incompatible due to anyone doing 'reflect.TypeOf' which I guess you could
argue is fine to break.

Speaking of reflection, there's a metric _TON_ of runtime panics in the
reflect package. Hell, I'm not sure there's a method in there that can't
panic.

No doubt, however, you'll say that's cheating and the expected behavior of
that package, so how about NewTimer (playground
[https://play.golang.org/p/jDKniK3aqa](https://play.golang.org/p/jDKniK3aqa)
). It does not give me an opportunity to recover from bad input by passing an
error out, it just panics. It is also not documented that it panics afaik and
other functions in time (time.Sleep) take negative durations and handle them
just fine. This is definitely inconsistent with other std library functions
that can take bad input and return errors.

I also think it's disingenuous to say "Keep in mind errors are from C and at
least they're better than C"... the comment I'm responding to is a comment
regarding go std library being one of the most consistent (implicit compared
to _ANY LANGUAGE_ ) so I may bring in anything I wish, and sure Go's errors
are a step up from C, but they're awful compared to other languages. They're
basically passing around strings with no builtin way to create a trace of
errors to return up the stack to maybe be printed, no default way to create an
optional type with an error value, and no consistent way to determine which of
N errors it was that was returned from a function without using a regexp 90%
of the time because that damned fmt.Errorf / errors.New... And yes, using a
Regexp in your error handling _IS_ a problem.

> defined on float64, which can be annoying, but is far better than any
> alternative

Funnily enough, the 'rand' library implements everything by just having
multiple functions and postfixing them with types (rand.Uint32, rand.Int,
rand.Float32) and strconv does something vaguely similar.

Whether one or the other is better, that's another inconsistency in the
stdlibrary; do you have many functions per type or only one function for one
type? I have no clue how Go could have abused you such that you are able to
conceive of not having a builtin int64 compatible 'min' function as a good
thing.

Actually, perhaps your post is simply a plea for help as Go has tied you up
and holds a gun to your head, in which case I suppose we should mount a rescue
mission forthwith! Just let me write a quick timer to keep track of our
progress... -1 you s.. err panic

~~~
comex
I don't know about consistency within the standard library, but NewTimer's
behavior definitely sounds consistent with the concept of distinguishing
programming errors from exceptional conditions. Passing a negative number as a
duration could either be defined behavior (equivalent to zero for programmer
convenience and consistency with the principle that timers can fire late) or a
programming error (should've checked that whatever you were subtracting to get
that duration isn't backwards), but it's not an exceptional condition that
can't be predicted in advance. Indeed, checking for a negative number, which
is rarely necessary, is no more code than the 'if err' thing, and if it isn't
necessary in a particular use of the function, you have the luxury of knowing
it can't fail, and you don't need to figure out what will happen if it does.

(I bet you'd be unhappy at Rust irrecoverably panicking the thread for simply
performing addition, if the result overflows!)

------
brandonbloom
Comments are also not metadata!

CGO, for example, expects a comment immediately before a special import
statement. A blank line between that comment and the import statement means
that the comment is not attached to the import statement's AST node, and so is
ignored. This confused me a fair amount when I started with CGO.

Part of the problem with comment syntax is that it's intentionally lexical and
uniform. This simplicity means that you can easily obliterate the content of
comments at any point in the input file stream via the tokenizer. However, Go
instead has to bend over backwards in it's compiler toolchain to preserve
comments beyond the lexer: in the parser, AST, code generator, etc.

Compare to docstrings in SmallTalk/Python/Clojure, where they are actual
parsed string literals. Also compare to C#, which has explicit and distinct
syntax for comments, metadata, and compiler directives. Comments can be
inserted more or less anywhere. Metadata only where it's unambiguously
attached to an AST node. And directives similarly to statements, unambiguously
detached from other AST nodes.

With proper syntax for metadata, the CGO case would have been a compile time
error about no AST node for the metadata to be attached to.

With proper syntax for directives, the //go:generate string-scanning bug would
have never happened.

These syntaxes must be disjoint from comment syntax to eliminate the problems.

~~~
sunnyps
Have you actually studied the go compiler implementation and found that
comments are preserved across all stages or are you just speculating?

I can imagine a design that works where only the lexer keeps track of comments
(with locations) and the remaining stages do not. In fact using comments to
generate code is not all that different from using comments to generate
documentation (like doxygen) and that shouldn't require comments at the AST
stage.

~~~
brandonbloom
> Have you actually studied the go compiler implementation ...

Yes. Though it's worth mentioning that they use the same AST infrastructure
for `go format` and `go fix`. That means they need to track comments anyway.
However, those use cases don't necessarily have the same requirements for
accurately matching comments to semantically meaningful nodes.

> using comments to generate documentation (like doxygen)

1) I don't really believe in javadoc or doxygen really.

2) Even if I did, I'd prefer actually (and similarly lightweight!) metadata
notation.

3) Also consider runtime documentation support. eg:
[https://clojuredocs.org/clojure.repl/doc](https://clojuredocs.org/clojure.repl/doc)
and
[https://clojuredocs.org/clojure.repl/source](https://clojuredocs.org/clojure.repl/source)

------
marcus_holmes
At last! I'm not insane!

I raised this on the golang dev forums and got nowhere:
[https://groups.google.com/d/msg/golang-
dev/r4rdPdsH1Fg/yjOOz...](https://groups.google.com/d/msg/golang-
dev/r4rdPdsH1Fg/yjOOzqIqNPMJ)

The response was basically "we disagree" and I wandered away feeling confused
that so many bright people couldn't see the problem here.

~~~
chimeracoder
> The response was basically "we disagree" and I wandered away feeling
> confused that so many bright people couldn't see the problem here.

That's a rather disingenuous summary given that literally the _very first
response_ is Brad Fitzpatrick from the Go team agreeing with you,
acknowledging that it's unfortunate, and admitting that it can't feasibly be
changed yet due to the compatibility guarantees. And then shortly afterwards,
he encourages you to bring this point up when Go 2 comes around.

~~~
pjmlp
I doubt that there will ever be a Go 2.

EDIT: For the downvoters, quoting Rob Pike in one of his presentations, "Go's
design is done".

~~~
ominous_prime
Maybe he should have said the design is done for go1.

Regardless, issues are still filed under the tag of `go2`, even by Rob Pike.
There's no reason to believe that go2 won't eventually happen.

~~~
garthk
On the other hand, there's every reason to believe the "Go [a]Way" prohibition
on certain language features will leave Go 2 insufficiently attractive vs Go 1
to overcome the switching costs, dragging out any migration period. See also:
Python 3.

------
breakingcups
The problem with Go is that, while the language and compiler are excellent,
Google doesn't a lot care about tooling & ecosystem. Why? They have their own
in-house tooling (which is of course both highly specific to Google's use case
and closed of for the public).

This in itself isn't bad, but the problem it causes is that the Googlers (who
do not experience the pain that other users of the language do) are still the
majority voice in any decision. Maybe not in numbers, but definitely in
weight.

There have been a number of changes pushed through that make sense in Google's
use case but not for general development use. Stuff like declaring a folder
named "internal" special where it wasn't before. Perfectly understandable in
Google's internal uniform codebase, where nearly every package is understood
and the world is small. Not a smart change to make a few years into the 1.0
compatibility freeze though, since you can bet that a lot (I even dare say a
majority) of 'regular' developers won't know about this and might run into
problems because of this at one point or another.

This is just a small example that I can recall out of the top of my head but
my worry is that this is happening more often with a lot of features.

Counterarguments from Googlers are usually along the line of "Go has X
contributors, only Y of which are Googlers", but that is not the full truth.
The top 5 contributors are still employed by Google. If you read the golang-
dev mailing list, especially when it comes to discussions about tooling and
ecosystem, you'll see that the Googlers have an overwhelming voice and will
not shy away from flat-out rejecting criticism to proposals that might be nice
for Google's use case but cause ambiguity and complexity for other developers.

Having said that, I still love the language and design. I just whished they
shied away from magic comments and half-baked solutions for dependency
management.

~~~
zaphar

        The problem with Go is that, while the language and 
        compiler are excellent, Google doesn't a lot care about 
        tooling & ecosystem. Why? They have their own in-house 
        tooling (which is of course both highly specific to 
        Google's use case and closed of for the public).
    

This is the most bizarre criticism of go I have ever heard. Go has the best
tooling of any language I have ever used bar none. A cursory look at:
[https://godoc.org/golang.org/x/tools/cmd](https://godoc.org/golang.org/x/tools/cmd)
shows a list of tools I've been wanting in Java and C# for _years_ and they
practically come out of the box for go.

* Automated refactoring that is editor agnostic? check.

* Editor agnostic built in documentation tool/server? check.

* Editor agnostic Code analyzers/oracles? check.

Go's core dev team is many things but saying they don't care about tooling and
ecosystem is a gross misrepresentation. They may not care about your specific
IDE or preferred language design but they most definitely care about making
tooling available to _everyone_ regardless of IDE/editor choice.

~~~
tomjen3
Eclipse has had those things for years for Java. Yeah that is not editor
agnostic but when you sit down and learn a platform learning an IDE isn't a
big deal.

Speaking of which I do not see any official recommendation of an IDE for Go.

~~~
fixermark
That's the point---rather than create a tooling ecosystem that forces a
particular IDE choice upon developers, Go is aiming for a set of minimally-
sufficiently-powerful tools that IDEs can hook into.

Learning an IDE isn't a big deal, but it isn't, say, preferable to not having
to learn one. I know Eclipse, but I avoid using it in all contexts where I can
---it's slow, its project model borders on filesystem hostility (and still
sometimes requires a "throw up your hands and delete a bunch of dotfiles"
solution to fixing breakages in it), and even after years of refactoring and
improvements it will still go "out to lunch" on garbage collection and force a
pause in my process that most IDEs will not. Being forced to use Eclipse would
be a hindrance for me in picking up Go (and I think a similar argument can be
made for being forced to use (X|X element of IDEs) across all developers).

~~~
tomjen3
>Learning an IDE isn't a big deal, but it isn't, say, preferable to not having
to learn one.

Everything else being equal, perhaps you are right. However by blessing one as
the official editor the tools can be written to work with that rather than the
lowest common denominator. This will make it more difficult for alternatives
which is a cost, but I do believe the upside is worth it - unfortunately I
can't prove it.

------
aikah
I 100% agree. You want macros? I don't like it but think about proper macros.
Go generate is just sweeping issues under the carpet and say to developers "it
has been dealt with". Nobody expects a language to be perfect, but sometimes I
feel the Go team takes devs for idiots with half baked solutions. So don't use
comments for anything but documentation generation purpose.

.

~~~
enneff
> Go generate is just sweeping issues under the carpet and say to developers
> "it has been dealt with", which is ,at the minimum, insulting. Nobody
> expects a language to be perfect, but sometimes I feel the Go team takes
> devs for idiots with half baked solutions.

That's absolutely a mischaracterisation, and a hurtful one at that because we
absolutely care about our developer experience.

"go generate" is a mechanism for invoking code generation tools; tools that
people were already using in a variety of ad hoc ways. That's all. Macros are
another thing entirely.

Our conservatism should be a testament to how much we care about quality. We
don't want to do anything by half measures, as that serves no one's interests.

~~~
zak_mc_kracken
> Our conservatism should be a testament to how much we care about quality.

Offering code generation as a solution to code reuse is not caring about
quality, it's laziness.

~~~
dward
It's an opensource project. Why don't you contribute a better solution? Or are
you too lazy?

~~~
threeseed
Just because it is open source does not me (a) that your changes will be
mainlined, (b) that your changes will be even considered or (c) that you will
logistically be able to maintain an ongoing fork.

Saying "it's open source so you can just add feature X or change feature B"
only works if you are part of some core team or are respected via other means.
Github is littered with projects that have lots of Pull Requests that never
get pulled.

~~~
zak_mc_kracken
> Just because it is open source does not me (a) that your changes will be
> mainlined, (b) that your changes will be even considered or (c) that you
> will logistically be able to maintain an ongoing fork.

Or d) that I have any time in my life to undertake such work.

------
enneff
(You left out "// +build", which predates Go 1.4.)

We made the decision that "//go:" is the syntax for comment directives. The
old ones stay around for compatibility reasons.

Previous discussion: [https://groups.google.com/forum/#!searchin/golang-
dev/commen...](https://groups.google.com/forum/#!searchin/golang-
dev/comments/golang-dev/r4rdPdsH1Fg/yjOOzqIqNPMJ)

~~~
vorg
And there's

    
    
        //line path/to/file:linenumber
    

and

    
    
        //go:noescape

~~~
mattkrea
Reminds me of typescript

/// <reference path="../typings/tsd.d.ts" />

~~~
kevingadd
/// is metadata/docstrings - it's a convention from C#. So a /// block is
parsed by the compiler and tooling (to generate documentation xml files, for
example), while a // comment is not parsed at all, just stripped.

~~~
mattkrea
Gotcha. Although most of the guys I see use the /// <summary> stuff as
comments in the real world I guess I can see the difference.

------
lohengramm
I also do not agree with that. This is bad for so many reasons. First, to the
compiler code, comments should be discarded as soon as possible (often in the
lexer). To the programmers, comments should never execute anything (this is
just intuitively expected). To any go source code reader (human or machine),
comments are supposed to contain only human readable text, probably a context
sensitive explanation of that particular section of code. To the separation of
concerns, comments are comments and compiler directives are compiler
directives. To each his own.

This is probably the only decision I disagree with the Go team to date.

~~~
jackielii
the comment is not executed by the compiler, it's executed by the go tool

~~~
lohengramm
Thanks for the reply. I suppose this changes things regarding the compiler
code, but it is still an external tool parsing and executing comments. There
should be a better way of doing this.

------
fredkbloggs
The basic syntax of Go is C-like (this is not intended to be controversial),
including that of comments. There is also a C syntax for communicating with
the compiler: #pragma. There is no need for yet another syntax here. Just
follow the example set by the language that has already heavily influenced the
Go syntax.

Note that C compilers already have the attributes people are demanding here:
pragma directives are parsed, unknown pragmas generate errors or warnings,
they are both visually and syntactically distinct from comments (intended for
humans, not the toolchain), etc.

Solved problem. There's no reason to invent new syntax here.

------
egeozcan
To this day, I still couldn't figure out why Go stays at the edge of being a
great language, but lacks few very essential features for -to me- inexplicable
reasons.

Look at all the work done on JavaScript to generate code from macros and how
incompatible the libraries became (JSX, sweet.js, TypeScript and so on). If
there's no standardization, I'm afraid, go may have the same destiny.

If anyone on the Go core team is reading this, I'd like you to consider adding
proper macros to the language.

~~~
rudolf0
A more conservative approach to macros would also just be... generics.

------
hartcw
Although I don't use go (yet), I can see the benefit of this mechanism as I
use a similar one for my own c/c++ code. There I use specially tagged comments
to embed python in the c/c++ sources, and then run all the code through a
python interpret stage to expand/execute the python code before compiling it.
Actually it supports C macro style for the embedded code, which is a bit more
sensible than misusing code comments.

For example for generating a c/c++ enum:

    
    
        enum example_t
        {
            #py \
            for line in open('values.txt'): \
                print('EXAMPLE_' + line.strip() + ',')
            EXAMPLE_Max,
            EXAMPLE_Unknown
        };
    

Or alternatively to stuff it in a comment:

    
    
        enum example_t
        {
            /* py
            for line in open('values.txt'):
                print('EXAMPLE_' + line.strip() + ',')
            */
            EXAMPLE_Max,
            EXAMPLE_Unknown
        };
    

If anyones interested, heres the python script I use to preprocess the c/c++
files [https://github.com/hartcw/cppy](https://github.com/hartcw/cppy)

~~~
threeseed
Sure the concept is definitely useful. But overloading comments seems
monumentally dumb.

They should have copied Java's annotation model which makes a lot more sense.

------
_yosefk
One language where this is currently practiced is Verilog. To make things
spicier, different vendors have different syntax for semantics-changing
comments, often prefixed with the vendor's name.

One "benefit" of this is that an older tool not updated to include the new
syntax embedded in the comments will remain blissfully unaware of its
ignorance, instead of spitting an error message. Another "benefit" is that a
programmer unaware of the syntax might delete or copy & paste such comments
when doing massive editing, without realizing that they aren't comments. To
achieve the latter, it helps if the syntax looks like English or, better yet,
if it looks like commented-out code (and, come to think of it, it's not
unlikely that it will look like at least one of these things.)

------
bane
As soon as you start using comments for something other than comments or
documentation, you've basically admitted the language is broken and you end up
becoming Java.

~~~
oldmanjay
I don't understand the conclusion. Java is certainly verbose and a fair bit
aggressively ugly, but it has consistent syntax and I've never before heard
anyone describe it as broken. care to amplify?

~~~
bane
Well, not exactly comments, but Java's annotation system is an ugly kludge
that should be part of the language and not an attempt at reintroducing
C-style compiler directives.

The abuse they suffer under various frameworks and ORMs is one of the ugliest
things I've ever seen in a language. In almost every-case they either serve
little to no purpose, or would be better-off just being part of the language
syntax. But now you have to learn Java, and the Java-annotation meta-system.

At least they aren't written in XML.

 _note_ I actually don't mind the Java Community's habit of usingLongNames for
things, and the actual language is pretty small and nice.

------
copsarebastards
What's the point of having a single-pass compiler if you have to add hacky
precompilation steps to make up for its shortcomings? If you're passing over
the code multiple times anyway then it defeats the purpose.

------
fixxer
Meh. I hear your gripe, but I think your proposed solution is not that much of
an improvement. You're also basing all of this on the idea that comments are
"free form". Where is that gospel? I like the idea that comments are more than
just blabber. I like the idea that, when structured some way, they take on new
meanings.

I think this is a semantic argument.

~~~
Merkur
I too like the idea that comments are more than blabber. I do use comments
like //BUG: //TODO: and //HOT:

My argument is semantic? Yes it is! In my optinion thats the reason my
argument is so strong.

Please dont tell me you dont see a problem between //go: foor and //todo: bar
- the first instructing some tool to change stuff in your build, the later
merly mention that there is something left to do here.

A directive like #todo: bar - is a great example for a great tool in the
chain. the go tool could look for a "todo" command and this todo command could
print out a warning that the code should not be released because XX todos
arn't done. If the go tool would'nt find a "todo" command it could warn me
that a tool in the chain is missing. I could evaluate in decide to use get
this tool, or choose to ignore it.

This would be imposible if comments are missused as directives!

~~~
fixxer
Now argue against yourself and prove you understand why you hit resistance.

~~~
Merkur
if you can agree that i got arguments that convince - i do you the favor. :)

~~~
fixxer
I agree that you have raised an argument. I haven't read anything to indicate
you understand the issue at a higher level. It would definitely help me
respect your argument as sincere if you argued the counter with
sophistication.

~~~
Merkur
okay, i'll jump :)

1) First of all change is not nessesary - because within the current "comment
directive convention" the tooling needs can be achived. Even more so - they
can be achived without changing the current spec of the language.

2) As I learned during this discussion there are "comment directive
convention" that are older as go 1.4. I could imaging they play a role deep
inside the go tooling. i.e. I could imaging that the cgo stuff has some deep
roots. It would some work to change all occurences - that is glass clear -
because even now there are legacy directives // +build //link that are not
updated to the "new convention" //go: foo

3) I dont know about the internal mechanism that the go team needs to observce
to change the spec of a language, that is perhaps in wide productive use
within the google. But i can imagin there is procedure. Changing the spec
meight just not be possible before Go 2.0 because of policy.

4) It meight not be desired to introduce something that smells like a macro
language into the code. There meight be some animosity againt it - give the
clean code philosopy that Go aimes for.

No, i dont realy believe that. I am Sorry to have accused! On contrary: The
yacc tool gives great power to expand the language. But yacc is a heavy
lifting tool and not something like a macro every one could use. Its also not
part of the spec, just given as magic comment - no prommise made.

5) One counter argument that is invalid: I am pretty sure the go team cares
about semantic. :-) All programmers do breath semantic. Of course there are
different tastes.

6) You basicly cant prevent magic... in comments or otherwise its the reason
its called magic.

7) those commented directives can stay in all levels of the build process -
without adaptions of the spec. This means tools have the potential to hook on
source, on ast, etc.

~~~
0xdeadbeefbabe
> One counter argument that is invalid: I am pretty sure the go team cares
> about semantic. :-) All programmers do breath semantic. Of course there are
> different tastes.

I put up with whatever semantics are necessary to get the CPU to do the right
thing, but I'm more excited about CPUs than semantics.

~~~
Merkur
well, i see - my statement was flawed. :)

~~~
0xdeadbeefbabe
You stand corrected then :) (or not). Does this comment thing make you want to
flee to the safety of Java? I would put up with Java semantics if I were
fulfilling a community service sentence.

~~~
Merkur
Actually it would remind me on C. It did not even support a redundant comment
token, and of course they did not used a comment to mark directives.

go troll your self. I am always open to argue, but you have no leverage to be
snarky.

~~~
fixxer
Your entire tirade is a troll. You got an answer from Fitz (looked reasonable
to me), but you didn't like it. So you decided to take the debate to HN?!
Nothing productive ever happens like this. This is some teenage angst
diarrhea. Fork the project and write your own solution. Show us all how
fucking brilliant you are.

~~~
Merkur
while arguing against your self is nice practice - diarrhea is just... you
know... really messy. I hope you get well soon. :)

~~~
fixxer
Oh no, you misread what I wrote. I was comparing your tirade to diarrhea. As
in, "I think your words are shit".

Sorry for the mixup! Take care!

------
saintfiends
Partially agreed. Directives should be visually distinct from comments and
syntax should be formally defined such that compilers, code generators,
editors and IDE's can use them consistently.

~~~
NateDad
The compiler doesn't need to care about these directives. They don't have
anything to do with the compiler. That's half the reason they're _in_
comments. Otherwise you're just adding _another_ kind of comment the compiler
has to also ignore.

The directives _are_ pretty visually distinct. You could easily configure your
editor to highlight them differently if you so chose.

~~~
saintfiends
1\. I don't understand what you mean by "They don't have anything to do with
the compiler"

[https://golang.org/cmd/gc/#hdr-
Compiler_Directives](https://golang.org/cmd/gc/#hdr-Compiler_Directives)

2\. I could keep adding syntax support as they come along and handle all the
inconsistencies, but that is not a solution. It's a hack.

------
nicerobot
Just because _you_ are locked into a mentality about a meaning for // does not
mean we all are. Explain to me why formatted/structured text can not appear
after a // in a file. If your editor parsed the text and formatted it to look
meaningful, like code, would that help?

~~~
henesy
I'm not sure why it bothers everyone so much. I might be missing something,
but unless people are writing their comments in a very specific style then it
shouldn't cause issues. From the help: "(note: no leading spaces and no space
in "//go") where command is the generator to be run, corresponding to an
executable file that can be run locally." It just seems like the code is
distinctive enough it shouldn't cause problems. Or, if style should be
adjusted, why not write your "not code" comments using the /* */ style?

~~~
stefantalpalaru
What part of "all syntax should be validated" don't you understand? By putting
that syntax in comments, syntax errors will not trigger any output from the
tools because they remain valid free-form comments.

~~~
henesy
And they're not "Go" syntax. The syntax in the comments if for Go tools. A
better approach may be to provide a more extensive syntax checking tool that
parses comments and checks for syntax errors on a per-tool basis, but as I
understand it it would seem that the implementation as it is now is aimed at
the auxiliary Go tools, standardizing the syntax for the tools, thus
allocating potential for future tools to expand without extensive maintenance
on the core language itself. The tools are not the core language, but there
should probably be some form of syntax checkers for the tools, but perhaps
encapsulated within the tools. The comments are still comments to the actual
Go code, as they are not pertinent to the language itself, but rather an
outside entity such as a tool. It is also entirely possible that I am missing
the point entirely and do not understand.

~~~
stefantalpalaru
It's irrelevant which tool does the checking. The problem is that you don't
know whether "// go:generate foo", "//ho:generate bar" or "//go;generate baz"
are errors or simply comments.

In order to detect most of that you'll have to redefine the comment syntax for
the core language so it's no longer free-form but anything that looks like a
comment-directive now triggers a warning (or most likely an error seeing the
Go philosophy).

------
nulltype
I don't really agree. I don't see any substantial difference between //go: and
#go: except that programs using the # syntax would not build on older versions
of go. I haven't really run across any issues with the current syntax. What
kind of issues are you having?

~~~
masklinn
The difference is that an innocuous comment can (and inevitably will,
especially since Go apparently does not actually care about comments, only
that a line starts with //go:[0]) match the directive syntax at some point and
then it's a right pain in the ass to debug, if that doesn't break anything.

[0]
[https://news.ycombinator.com/item?id=9523187](https://news.ycombinator.com/item?id=9523187)

~~~
nulltype
I think they should fix that bug where it's not actually looking at the
comments. However, with the exception of that bug, I don't think I have ever
made a comment that started with "//go:" and was not a directive. It seems
kind of hard to make one of those by accident.

------
donatj
I honestly even feel weird about godoc just being standard comments, in my
mind docs and comments are different things, docs usually being noted with / *
* (no spaces, but can't figure out how to escape) and comments being /* // or
#

------
jdkanani
I couldn't agree more. It also makes code hard to read. I have to look closely
to check if that's a comment or directive. It would be problem when your code
grows.

I am in favor of #TAG: DIRECTIVE or @TAG:DIRECTIVE

------
dvirsky
This pattern predates Go 1.4, we've had it with CGO and build tags since at
least 1.0 AFAIK. Even the Output in examples is pretty old I think. The only
advantage in it is backwards compatibility with older Go versions, but in
general I agree with you.

When PHP did it for Python-style decorators everyone thought it was stupid.
And while the build tags in Go are okay by me, doing it for CGO especially
seems like a hack.

~~~
mappu
AFAIK PHP doesn't provide python-style decorators and never executes code
within comments. Can you cite that? Or are you maybe using a framework or
library that's re-parsing your source files?

~~~
EugeneOZ
PHP never execute comments, be sure. Some frameworks and tools like Doctrine
use comments and reflections to prepend comments are annotations, and it's one
of the reasons why these frameworks are slow as hell.

------
scott_s
I don't know enough of the matter to have an informed view, but I think it's
worth noting that there is precedent for this sort of thing. Take from one of
my Python scripts:

    
    
      #!/usr/bin/env python
    

[http://en.wikipedia.org/wiki/Shebang_%28Unix%29](http://en.wikipedia.org/wiki/Shebang_%28Unix%29)

~~~
bozoclownn
I would add that this technically is a (ba)sh script, not a Python script.

~~~
tangent128
On *nix systems, the #! is parsed by the kernel as a magic number. sh/bash are
not involved.

~~~
bozoclownn
Thanks, didn't know!

------
amelius
To be fair, it all started with #!/bin/sh

------
erikb
What does the word directive mean? Doing stuff by parsing comments is called a
macro processor (or preprocessor, but it doesn't have to be done before the
actual processing) or not? I think there are many instances where macro
processors are a good thing. Some languages have them in the core. So what's
the difference between macros and directives?

~~~
Merkur
I would define a directive as an instruction to the tool chain.

A macro processor could be one of those tools in the chain. There could be
other (and Go implements other use cases!)

I would also argue that a macro preprocessor do'snt need to "parse comments",
it could parse any syntax the preprocessor wants to (and remove it from source
befor the compiler sees it) In fact my point is, that parsing comments at all
is a very bad idea.

But my argument is NOT about, if Go needs a macro processor, or not. (i think
it dont!) My argument is about the syntax of the directive.

I argue about the syntax of declaring "Here comes something that is not Go
Language!" I argue that this syntax should not be a comment - because a
comment is part of the Go Language. (...among other reasons i stated in this
discussion)

~~~
erikb
Okay, now I get it. Thanks for clearing that up.

I have to agree that adding features into comments instead of new language
blocks or frameworks is smelly.

~~~
Merkur
thank you, for beeing open to be convinced :)

------
donlzx
Comments are just comments, we should not keep adding keywords and syntax to
them.

Go's backward compatible promise is hurting itself. By sticking with strict
compatibility mode, ad hoc solutions for fundamental issues are added from
time to time. Sooner or later, those patch works will back-fire.

For a language so young (version 1.0 in 2012), they should keep compatibility
for stable release (1.x), but start adding language features in 2.x branches
ASAP.

Yes, compatibility promise may help selling the Go language at the beginning,
but Go authors may seem a little too confident/optimistic of the language
spec. in this case. If a 2.x branch is not coming out soon enough (in about
two year), we will probably face the same dilemma as Python 2 vs 3.

~~~
Merkur
One of the best features of go is "go fix" Yea! A migration tool for the
language it self? Before they need to worry about compatibility they can break
a lot of stuff.

~~~
donlzx
Yeah I know, we can easily fix the codes with tools, we also have tools for
conversion between Python 2 and 3, right?

However, we can not easily fix the way people writing the code, or the so-
called idiomatic Go norms.

Actually, it is compatibility in the ecosystem of Go packages that matters. We
have lots of good Go packages on Github that are no longer compatible with Go
1.0/1.1/1.2 etc.

------
aablkn
Oh don't forget the good old

    
    
        // +build !linux
    

build constraints feature. It's been there since go 1.0 afaik.

------
bsaul
Agree as well.

They could use the same convention as typescript and use a triple slash
instead. That wouldn't change much of the language and impact IDEs, but at
least distinguish between human comments and tooling instructions.

~~~
enneff
What's the difference between "///" and "//go:"? The latter is Go's official
convention, it's just that unfortunately some of our older mechanisms predate
the convention.

~~~
anatoly
What do you mean "Go's official convention"? Go is a language; it has a spec.
Is it in the spec? No. What is this "Go" that this is an official convention
of, and where is it standartised beyond your comment?

------
yyhhsj0521
In Python, following comment

#- _-utf8-_ -

indicated the encoding of a source file. In most cases, this won't induce
ambiguity, though it's potentially dangerous.

~~~
mpdehaan2
I was going to say it's the only one Python 2 has, AFAIK. So they've kept it
reaosnable there, but then I remembered this:

[https://www.python.org/dev/peps/pep-0484/#id24](https://www.python.org/dev/peps/pep-0484/#id24)

Which is pretty scary, IMHO.

Python is productive, but I always questioned some of the choices in the
language design (broken lambdas, etc -- though the implementation of list
comprehensions were great so I just learned to love them) -- but it seems to
take some of the same decisions Go is taking in terms of inconsistencies now.

The Go stuff, however, seems much more worse.

The phrase "nothing but Perl can parse Perl" comes to mind :)

~~~
kbenson
Python's list comprehensions always struck me as an odd way to go given
Python's tendency to choose clarity and simplicity over complexity and
expressiveness. As a Perl user, Python list comprehensions make me go cross-
eyed half the time. It's something Perl specifically decided to forego as too
complex and prone to causing confusion, which is saying something.

~~~
mpdehaan2
Nesting them I feel is almost always bad

blarg = [ foo(x) for x in y if x > 2]

I think is pretty decent. Helps if they are calling named functions, so it's
more self documenting, depending on complexity.

Dict comprehensions can be a little brain-warping too :)

~~~
kbenson
Yeah, the Perl equivalent of that is:

    
    
      my @blarg = map { foo($_) } grep { $_ > 2 } @y;
    

A bit more verbose, but if you know Perl, obvious (and the same building
blocks allow for more powerful constructs[1], since they really are functional
code blocks).

You can argue the Python version is clearer, but placement of the conditional
always throws me off. I like to think of my transforms as a pipeline.

1:
[http://en.wikipedia.org/wiki/Schwartzian_transform](http://en.wikipedia.org/wiki/Schwartzian_transform)

------
rjsw
Lisp has used directives in comments in the past. Only on the first line of a
file but they were parsed.

~~~
Grue3
That had to be very distant past or some non-standard lisp. Common Lisp has no
such feature.

~~~
lispm
That's a feature of the Lisp IDE.

File mode lines described language, the syntax (which Lisp dialect), the
Package, the numeric base, the encoding, ...

Example:

    
    
        ;;; -*- Mode: lisp; Syntax: ANSI-Common-Lisp; Package: http; Base: 10 -*-
    

But to implement compiler directives in Common Lisp, this is not needed. That
can already be done with macros and reader macros. If you for example use a
macro in source code, the compiler will need to expand it. That allows
arbitrary code execution during compilation.

------
cjslep
Sad to see Go is fully going the way of Intel's Fortran compiler. It was more
reasonable when (I think in cgo) you needed to export functions, which is done
in Intel-compiled Fortran like so:

    
    
        !DEC$ ATTRIBUTES DLLEXPORT :: NameOfSubroutine
    

Also at least Visual Studio will color those comments differently than normal
comments.

------
anacrolix
I think the same can be said of the . selector on packages.

------
turrini
//go:fancy

seems more appropriate.

------
khanhussan
:p -_- very nice

------
Dewie3
If you're feeling paranoid and don't have time to look up the set of magical
incantations, maybe you should write your actual comments like this:

    
    
        // COMMENT we have to check that [...]
    

:)

~~~
Merkur
Code should not be magical. Magic is bad engeneering. Magic involving a
whitespace is madness.

~~~
Dewie3
My intent was to poke fun at the current state of things. Not to give actual
advice. :)

