# 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.
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.
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.
EDIT: For the downvoters, quoting Rob Pike in one of his presentations, "Go's design is done".
http://fixunix.com/plan9/523380-%5B9fans%5D-using-acme-edito...
Elegant design...
> But I disagree that putting commands in comments at all is a good idea. Just because other languages do it doesn't make it a good idea. It's clearly a hack to get around some historical problem, and we're better than that.
A member of the Go team says:
> Where you see a hack I see an elegant design.
It's never been an elegant design, at best, it was an acceptable design in the 90s.
I don't see why that's so hard to imagine. Just because someone is skilled/bright in some area doesn't mean that they are skilled/have good taste in another area. Even if those areas are very similar from a high-level view, like both involving programming.
There has been a lot of appeal to authority with regards to the Go designers/developers - basically that they have a long track record of making great/influential software. And though appealing to authority certainly isn't without merit, I think it was taken a bit far, namely that it was used as an argument to try to end all discussion. And secondly the things that they are famous for does not seem to be related to PL/design.
If I had a huge amount invested in Go I would consider forking it - it is one thing to have a benevolent dictator, but if he doesn't at least listen then there is no point at all.
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.
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 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.
I've heard this explained as "everyone at Google just points their imports at Git repo HEADs", which is valid for a self-contained organization like that, but seems very closed-minded considering they want this language to be adopted universally.
Speaking of which I do not see any official recommendation of an IDE for Go.
https://news.ycombinator.com/item?id=8733705
I was severely downvoted and did not get many who agreed with me.
I'd say you got this exactly backwards. The language is mediocre, but the tooling and ecosystem are great.
The `go` command in particular is something I really want in other languages: no messing around with build files or monsters like `cabal`.
Where can I read more about this?
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...
For an example of what this looks like in actual use, see the very popular go-sqlite3 library: https://github.com/mattn/go-sqlite3/blob/dee1a37fe11067e9797...
I personally think that large block-comments of code that actually do something, but only if above a certain import really strange and unexpected; it means re-ordering imports can break things, changing around spacing can break things, and tons of other things.
//todo: bar
to do stuff with the code, and makes the program fail because it's not done, because you don't know about it. with a #todo: bar the go tool chain would catch this error
All of these of course are minor things. Go does a lot of things very right like easy of concurrency, scope and quality of the standard library and easy of deployment. Looking forward to the GC improvements in the near future as well as a day when we get generics. I'll be a happy camper then.
//line path/to/file:linenumber
and //go:noescapeIn 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.
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.
I think that was the case with Go from the start. Can you think of some aspect that was especially well thought-out?
Interesting contrast to the philosophy of Perl 6: 'torture the implementor on behalf of the user'.
"Every language contains novel features and omits someone's favorite feature. Go was designed with an eye on felicity of programming, speed of compilation, orthogonality of concepts, and the need to support features such as concurrency and garbage collection. Your favorite feature may be missing because it doesn't fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.
If it bothers you that Go is missing feature X, please forgive us and investigate the features that Go does have. You might find that they compensate in interesting ways for the lack of X."
.
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.
I actually don't think this was an unfair phrasing. I had actually felt insulted when `go generate` was announced. "You're sweeping [generics et al] under the rug using comment-bound directives and telling me it's an elegant solution to problems? Do you think I'm an idiot?" Was, in fact, very close to what went on in my head when I read that initial post/slideshow.
I don't like to be degrading when it comes to differing opinions on coding practices - if generated code and comment-bound directives are good for you, well, okay - but being told that I should like it and stop questioning? That's insulting.
I think the deeper complaint that's coming through is not that the Go team are bad language designers who don't care about the developer experience, but that they are condescending towards the community. Even if you really, really don't mean to be.
As long as it aligns 100% with the bizarro ideas of the core team regarding comment pragmas, code generation, vendoring, generics, etc.
Offering code generation as a solution to code reuse is not caring about quality, it's laziness.
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.
But the complaint is about //foobar: and that is just confusing.
the main problem is not technologie but semantic. If you agree with me that the meaning of a comments is communication between humans, than you must also agree - in my opinion - that comments can not be directives to a tool chain.
It is ambiguous. It is error prone. It is easily solved using an other token.
And in the long run it may lead to madness like Java testing and documenting frameworks.
as for technical problems - I think some really bad ones are mentioned in this very discussion!
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.
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.
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 and https://clojuredocs.org/clojure.repl/source
This is probably the only decision I disagree with the Go team to date.
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/cppyThey should have copied Java's annotation model which makes a lot more sense.
These problems are exactly why this is unacceptable in Go. Go has the benefit of learning from C++'s mistakes and seeing other attempts at solutions to the problem. Language designers have made these mistakes before, realized they were mistakes, and come up with better alternatives. This is just another example of the Go team either being unaware of or ignoring decades of development in programming languages.
Something like PY_CODE(<blah>), for instance. That way it won't compile unless you run it through the preprocessor.
enum_example_t
{
#include "example_values.txt"
EXAMPLE_Max,
}
where example_values would have the strings 'EXAMPLE_foo,'?
Just wondering.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.
So what if you have a bit of code that you are half way through and you want to comment it out as well as the imports. I've done this countless times over the years.
#--utf8--
indicated the encoding of a source file. In most cases, this won't induce ambiguity, though it's potentially dangerous.
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 :)
Remember that Python has supported function annotations since 3.0 [0]. Python 3.5 will only add the option to type check those same annotations.
Any type annotations that can be checked by Python 3.5 can also be parsed by earlier versions of Python, though without being checked.
The only wart in this master plan is specifically the one where you want to type annotate variables (as opposed to functions). Comments are the only way they could do this in a backwards compatible way.
The Python devs are well aware of the ugliness of this compromise, which is why they end the section you linked to with this:
> If type hinting proves useful in general, a syntax for typing variables may be provided in a future Python version.
I can't comment on Go, but I wouldn't call Python's choice here unreasonable.
IF has a meaning - and it always have this meaning. FUNC has a meaning - always the same. // are comments. The meaning of comments is to communicate with humans.
We know the principal of "overloading" syntax. Things can have a different meaning in a different context. One could argue using //go: is overloading the comment. BUT: Go is not a language that do's overloading - in fact its philosophy is against overloading, as it is against generics. (and I realy like this philosophy!)
I argue that directives to the tool chain should not apear in a comment - because a directive to the tool chain has a different & incompatible meaning than a comment.
I argue future: There is a need for directives to the tool chain in the Go source code. The go-team has this need, and there can be great things done with such e mechanism. The go community will do great things with directives! I see tons of use cases for godep. I see tons of use cases for debuggers, profilers and all kinds of other tools.
The go-team not only implements go, they also set an example to the usage of the language. If they misuse comments to express directives, other projects will eventualy follow.
But what will happens in the long run if we embrace that example and use //foo: bar as directives for our tool chains?
The go tool chain could not generate meaningfull errors about missing tools, or syntax errors in directives. Also: Comments would not be safe to communicate with fellow programmers - who knows that kind of tools where used in my dependencies? And what kinds of //foo: should be marked pink in my editor? All of em?
All this could be solved by using an other syntax for directives. I do not care if its # or @ or #! or whatever - as long as it is not a comment.
I also have no argument about macros, generics or whatever. I just want go to be unambiguous.
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.
#!/usr/bin/env python
http://en.wikipedia.org/wiki/Shebang_%28Unix%29The various shells are just a subset of the possible programs used.
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.I think this is a semantic argument.
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!
The directives are pretty visually distinct. You could easily configure your editor to highlight them differently if you so chose.
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.
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)
I have to agree that adding features into comments instead of new language blocks or frameworks is smelly.
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.
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.
// COMMENT we have to check that [...]
:)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.
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.
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.)
I am in favor of #TAG: DIRECTIVE or @TAG:DIRECTIVE
// +build !linux
build constraints feature. It's been there since go 1.0 afaik. !DEC$ ATTRIBUTES DLLEXPORT :: NameOfSubroutine
Also at least Visual Studio will color those comments differently than normal comments.seems more appropriate.