from Hacker News

Go Lang: Comments Are Not Directives

by Merkur on 5/11/15, 5:59 AM with 219 comments

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:

# used to set a canonical import path for a package: //import "foo"

# used to generate code: //go:generate bar

# used to document the result of a example function: //Output: foo

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!

It is my optinion that if Go needs some kind of annotation, than there should be a new syntax for it.

I would propose that directives to the tool chain will be marked with

#TAG: DIRECTIVE

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.

  • by TheDong on 5/11/15, 7:17 AM

    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 (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/

    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.

  • by brandonbloom on 5/11/15, 7:51 AM

    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.

  • by marcus_holmes on 5/11/15, 7:43 AM

    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...

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

  • by breakingcups on 5/11/15, 8:18 AM

    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.

  • by aikah on 5/11/15, 6:44 AM

    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.

    .

  • by enneff on 5/11/15, 6:47 AM

    (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...

  • by lohengramm on 5/11/15, 8:32 AM

    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.

  • by fredkbloggs on 5/11/15, 4:50 PM

    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.

  • by egeozcan on 5/11/15, 9:46 AM

    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.

  • by hartcw on 5/11/15, 9:02 AM

    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
  • by _yosefk on 5/11/15, 12:13 PM

    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.)

  • by bane on 5/11/15, 12:10 PM

    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.
  • by copsarebastards on 5/11/15, 4:37 PM

    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.
  • by fixxer on 5/11/15, 1:01 PM

    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.

  • by saintfiends on 5/11/15, 8:02 AM

    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.
  • by nicerobot on 5/11/15, 11:14 AM

    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?
  • by nulltype on 5/11/15, 7:17 AM

    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?
  • by donatj on 5/11/15, 10:42 AM

    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 #
  • by jdkanani on 5/11/15, 7:44 AM

    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

  • by dvirsky on 5/11/15, 7:56 AM

    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.

  • by scott_s on 5/11/15, 1:49 PM

    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
  • by amelius on 5/11/15, 12:52 PM

    To be fair, it all started with #!/bin/sh
  • by erikb on 5/11/15, 9:36 AM

    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?
  • by donlzx on 5/11/15, 11:43 AM

    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.

  • by aablkn on 5/11/15, 9:27 AM

    Oh don't forget the good old

        // +build !linux
    
    build constraints feature. It's been there since go 1.0 afaik.
  • by bsaul on 5/11/15, 6:51 AM

    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.

  • by yyhhsj0521 on 5/11/15, 12:43 PM

    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.

  • by rjsw on 5/11/15, 9:43 AM

    Lisp has used directives in comments in the past. Only on the first line of a file but they were parsed.
  • by cjslep on 5/11/15, 12:00 PM

    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.
  • by anacrolix on 5/20/15, 12:46 PM

    I think the same can be said of the . selector on packages.
  • by turrini on 5/11/15, 1:01 PM

    //go:fancy

    seems more appropriate.

  • by khanhussan on 5/12/15, 10:16 AM

    :p -_- very nice
  • by Dewie3 on 5/11/15, 10:42 AM

    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 [...]
    
    :)