Hacker News new | past | comments | ask | show | jobs | submit login
Go Lang: Comments Are Not Directives
279 points by Merkur on May 11, 2015 | hide | past | favorite | 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.




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.


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.


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


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


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.


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


Yeah, but with C's old-school int values for errors, you can always make an equality comparison. The error interface in Go doesn't specify equality, so you can do "if err == io.EOF" in some cases and you're up a creek in other cases. Sure you can do if err.Error() == "String I'm expecting", but as the parent said, fmt.Errorf can easily make that impossible.


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


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


    $ curl http://golang.org/pkg/reflect/ | grep panic | wc -l
    79


> Do you have any examples of the standard library using panics to signal handle-able errors

Are those 79 handle-able errors, or are they programming mistakes?


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

It's also important to keep in mind that people who don't like Go's approach to error handling might not be in favour of the exception-handling way, either. :)

https://news.ycombinator.com/item?id=9439948


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

My biggest disappointments early on was not even having a Max/Min function for ints.


But there is for float64 ;)

I think this is a classic case of Go's need for "simplicity" hamstringing the language. When handling min/max, they had a few options:

1) Treat numbers as a special case and have a polymorphic min/max that operates on any number type. This is out of the question because it is obtuse and irregular and neither of those things are the "Go way"

2) Properly abstract over numbers somehow. This can be weakly done using Go interfaces but 1) it would require >, < etc to all be methods on the number types. But then Go would need operator overloading and that's not the "Go way" 2) using an interface is actually bad anyways because it doesn't make guarantees that input type =:= output type. To do that you need proper generics and then use a common subtype or take it further and use a Numeric typeclass. This is way too complicated and not the "Go way"

3) Write a min/max for every number type. Due to lack of overloading, each would be named accordingly (minInt64 etc). This is ugly and definitely not the "Go way"

4) Just use the most "general" number type and write min/max for that. You can just cast on the way in and out so this "works". It doesn't require API bloat or more language features, so it's the "Go way"


> 3) Write a min/max for every number type. Due to lack of overloading, each would be named accordingly (minInt64 etc). This is ugly and definitely not the "Go way"

Have a package for each type, so you can import the one you need (e.g something like math/uint64), and eventually can rename it on import as is best fitting. Also, make it an external package in golang.org/x (like godoc&al) so as not to be bound to promises regarding language stability while at the same time offering a centralized implementation.

> 4) Just use the most "general" number type and write min/max for that

This is precisely what strconv.ParseInt does[0], with some obscure, runtime evaluated integer magic values of all things (instead of readable, type-safe, compile-time asserted enums).

[0]: http://golang.org/pkg/strconv/#ParseInt


yet the "go way" makes computing really tough :

        x := 1
	y := 2.0
	z := x + y

Error : invalid operation: x + y (mismatched types int and float64)

So much that devs end up using float64 everywhere ...


> So much that devs end up using float64 everywhere ...

Which makes complete sense given it's webscale enough for nodejs.


Note that option 3 is the approach the 'rand' package took (see https://golang.org/pkg/math/rand/#Float32 ).

I guess not so much definitely not the "Go way", just not the go way for the math library.


Sorry, but I can't find what you're referencing with the "as mentioned above" on math; could you clarify?

My biggest problem with the math library was, IIRC, everything only takes float64s, which makes dealing with any of the other number types more difficult than it should be (I shouldn't need to cast an int to a float and back in order to get the max of two numbers).


It's quite good, but e.g. Java SDK has stuff that runs circles around Go's standard library regarding breadth and maturity, especially stuff added since 1.4 (nio, etc).

And some aspects of the Go SKD are horrible in practical use. Case in point, most things math related.


Well, yes. But Java's standard library is also huge and full of deprecated stuff. I have not done a lot of Java programming, but when I did play around with Java, I found myself spending most of the time actually browsing through the standard library's documentation (which is, to be fair, really, really good) looking for stuff.

Also, Java has a head start of nearly 15 years on Go, and the Java community is (or used to be, at least) pretty huge.

Not that this invalidates your point.


Add an extra 30 years to that. Java's designers didn't history of computer science and language development for the of sake "simplicity". (Generics, error handling, etc.)


Go has the poorest std lib I've ever seen.


Compared with? My reference point is python,java,clojure,c,c++. Python is huge and useful but messy and inconsistent. Java is huge and doesn't compose well. Clojure is underdocmented and hardly batteries included. C and C++ can't do anything useful without a bunch of extra libraries. From what I can see, C# is like java in this regard.

Go is a small incredibly useful and composable set of libraries that handles a vast amount of cases with a small amount of code.


I had the same feeling about Clojure, but it mostly has to do with non-standard libs. It's forced me to rely on reading source code a lot more than I did in other languages, so I'm not entirely sure that's a mark against it. I'm curious why you think that about Python, though. Care to illustrate?


> Can you think of some aspect that was especially well thought-out?

Go routines, channels and select. With very little else, it's possible to write some very useful code in a way that's concise, elegant and easy to reason about.


Only compared to something like C or explicit old-skool Java like threading. A lot of modern languages have CSP built-in or as a lib (Java, Scala, Haskell, Clojure, C++, Ada, Erlang, heck even Rust).

And Go is not quite expressive to address higher level, but common, constructs ( https://gist.github.com/kachayev/21e7fe149bc5ae0bd878 ) in a conceise and elegant way.

And if you access anything outside of channel provided stuff in Golang, you have to bring your own safety.


You seem very focused on what you can't do with it rather than focusing on what you can do with it. I've found, in practice, that you learn to adapt to not having that level of expressiveness and start thinking through problems the Go way. And I've come around to the viewpoint that expressiveness is also a liability of a language in addition to being a feature. Sharing code in a team becomes so much easier when using Go compared to other, more expressive, languages. And I've even come around to liking it for my personal projects too after returning to code I hadn't seen in months and immediately grokking it.

Maybe it's just my advancing age (for a programmer), but I find myself gravitating towards the "It's not finished when there's nothing left to add, but when there's nothing left to remove" mentality when it comes to programming languages. I find that I'm only willing to tolerate new language features when they introduce benefits that go beyond expressiveness.


> Maybe it's just my advancing age (for a programmer), but I find myself gravitating towards the "It's not finished when there's nothing left to add, but when there's nothing left to remove" mentality when it comes to programming languages. I find that I'm only willing to tolerate new language features when they introduce benefits that go beyond expressiveness.

Yes, "maybe it's just my experience and wisdom with regards to programming". Do you really expect anyone to fall for that crap?


It looks like from the comments on your gist, there are ways to do it. Whether it's expressive enough is subjective but it's worth pointing out that there _are_ solutions.


I love the workspace structure and the package versions policy. Definitely my favorite among the languages I used.


I have been using Perl for a long time, it did not get everything right when it first rolled out its object system. Through incremental improvements and backward compatibility the language has become very stable. Go is just getting to 1.5, so I expect it to have some issues at the beginning.


That $DOLLAR fix isn't just some "issue" at the beginning as though it was a design mistake or architectural oversight. It is flat out sloppy work.

If you are creating a programming language that wants to maintain backwards compatibility surely every check in you make would be as close to perfect. No ?


Agreed: Languages can evolve.

Perl has been around since 1987. I would expect Go (first released in 2009) to have learned valuable lessons from earlier failures. This particular set of features doesn't appear to be very thoughtful.


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

Interesting contrast to the philosophy of Perl 6: 'torture the implementor on behalf of the user'.


This is exactly the "Worse is Better" debate. We know which horse won last time, I would bet on the same one this time too.


uh - that's really bad! :(


https://golang.org/doc/faq#Why_doesnt_Go_have_feature_X

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


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.


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.


> 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 and https://clojuredocs.org/clojure.repl/source


Agree. Something like decorators could have been used instead.


Go is typical "hurr durr, Java an C# are obsolete" write-only code by people who only ever work on ephemeral greenfield projects with a lifetime of 3 months and therefore can tell exactly what software development is all about.


Such an inflammatory troll... Do you you even know who is involved in the Go project?


I think that's actually the point.

At their level of prestige they can kinda work on whatever they like instead of having to live through and slog through the kind of crap code that accumulates on a project where you have people far below their level working along side people only slightly below their level.

If you only ever work with fellow top performers, you never need the language and tool features that make it less to work with idiots.

And then they do things like this comment stuff.


That's both an appeal to wrongful authority and irrelevant.

You don't judge a software product by the credentials of who wrote it, you judge it by whether it's a good software product or not.


No, it was a question.

The statement was asinine. I'm legitimately curious if the comment owner knows who is part of the core team.


> I'm legitimately curious if the comment owner knows who is part of the core team.

Yes, I know. And I know perfectly well that Go at its current immature state would never have gotten the kind of attention and consideration if it had not been designed by Mr. Pike. While I believe that many of the warts of Go are by design, some are obviously not.


Tell me then why Go is being used to drive so many big projects? Docker just raised another $95m for fucks sake. Why should I listen to you? What are your qualifications? Sell me on your position.


> Tell me then why Go is being used to drive so many big projects?

False dichotomy. The fact that a language is being used for big projects (or used at all) doesn't mean it has great design. Think of PHP...

I also completely fail to see what Docker's funding has to do with Go's design.


Good design = it gets shit done. I don't care for PHP syntax, but it gets shit done. Any definition of good design beyond that simple metric is pure masturbation.

Docker is written in Go and $95m is more validation than you'll get in ten lifetimes.


Again, that says absolutely nothing about the quality of Go compared to other languages. You can write programs that work in Go, big deal.

Maybe it would have been easier or harder with another language? Who knows.

The valuation has everything to do with Docker's business model and nothing to do with the language they use to implement that vision.


So you think that the ability to execute a large project successfully implies nothing about the quality of the tools used to implement the project? I disagree.

At no point have I made a relative statement about Go being better than another language. The only claim I would ever make is that Go is well designed and effective for certain tasks, as demonstrated by use (validated by investment, which we can accept if we assume rational investors -- not going to debate that).

Now the claim that started this was that Go authors are greenfield celebrity programmers and they don't spend their time in the trenches (as indicated by certain parts of the language that some people - usually from "enterprise" languages - don't like; heavily and unapologetically paraphrased). That statement is asinine when you consider the background of the authors and the projects they've been involved in over their collectively lengthy careers.


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.


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


Actually you seem to be pretty disingenuous by ignoring the rest of the posts and focusing just on the first one. The overall tone of the thread seemed to be pretty dismissive and I doubt if a solution was proposed for Go2 that it would gain any traction.


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


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.


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.


I remember I reacted hysterically in Twitter about this change, somebody gave me link to your post and after reading first response of Brad Fitzpatrick I realized there's no chance for arguing or discussion - all decisions are final and community feedback isn't required.


This reminds me of Plan9 "Just say no" on the Acme editor (see number 6 in the link).

http://fixunix.com/plan9/523380-%5B9fans%5D-using-acme-edito...


I don't know what your reaction to that response was, whether you stuck with acme or not, but I'm now looking for another language to use instead of Go.

I thought at first that this reaction was just sour grapes ("nasty people on the intertubes didn't like my post"), but as I analysed it more I managed to pull out three elements:

1. If my sense of elegance and the Go team's sense of elegance is this divergent, then the language will probably get uglier to my eyes as it continues to evolve.

2. If this is the reaction from the team to this (relatively small and inexpensive to fix) problem, then we can expect absolutely no movement at all on the bigger and harder problems (dependency versioning, generics). I used to have faith that these very smart people will come up with an elegant solution to these issues - I still love the simplicity and elegance of the standard library - but my faith has now gone.

3. Brad's response was amazing and I'd follow him anywhere, but... I don't want to follow the rest. If I'm to commit my time and effort to learning (and to a tiny extent popularising) the language and being part of the community, I want to believe in the people building it. I don't any more.

Humans are weird.


Agree with 1 and 2. And to clarify my comment: Brad's response is very detailed and I have nothing against it, I just see even Brad can't change things so these things will not be changed by community. I really respect Brad as a programmer.


Never used Acme. The answer always seemed to me weird, like "we are right, we do not care about this."

Just say no is a good slogan for "bad" things but pretending that syntax highlighting is "bad" is senseless.


Most interesting response from Russ Cox: "Where you see a hack I see an elegant design."

Elegant design...


They say that beauty is in the eye of the beholder.

meh.


Yeah. It makes no sense to believe that beauty is completely subjective, yet somehow related to software quality.


Beauty is in the eye of the beer-holder.


It's particularly baffling when, in response to:

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


That seems a general attitude from the Golang group. Same argument about generics, etc.

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.


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

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.


Actually it does. C was shaped to a large degree by feedback from the original Unix programmers, including Ken Thompson and Rob Pike.


Rob Pike? I thought that C came into its shape before his time.


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.


    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.


The thing that really baffles me is that Go/Google have invested so much into tooling for the language, yet didn't bother to implement official tools for the most important feature of any language: package and dependency management.

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.


I guess I agree with you, that from some kind of evolutionary perspective, having yet another language-specific package and dependency management system, this time for Go, might be a good way to boost popularity / uptake of Go. The system doesn't necessarily need to be a good idea, just quick and easy to use.

On the other hand, I think that dependency management isn't really a language specific problem, and it is silly to have different incompatible language-specific solutions for it.

E.g. I work mainly with Python, that has popular python-specific packaging tools, yet those tools cannot express dependencies of python libraries upon e.g. native libraries. The python-specific tools are convenient on a pure-python project, for multi-language projects it feels more like an anti-pattern than a solution, particularly if you end up having to use many different packaging ecosystems / tools.

I think google's approach makes more sense in the context of an organisation where some kind of uniform approach can be imposed, and particularly where there are uniform approaches to code quality / test coverage / continuous integration.

To be clear -- I have never worked at google, this is my external perception.

I have worked somewhere where there are simultaneous software projects with wildly varying levels of code quality / test coverage / continuous integration, this does not seem to agree with very well with the source-control-based "import from HEAD" in one big repository. The organisation is currently transitioning from this approach to more decentralised many-repository approach linked with language specific package management. I do not think this change is a clear improvement, but it does make some things easier.


This is admittedly a shortfall of go. However it's one that is fairly easy to rectify later and one the community is quite capable of solving itself.


Does go even have a usable debugger yet?


Depends on your definition I guess. I don't debug that often but when I have had to I've found the GDB debugger to be good enough for my purposes.


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.


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


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


It isn't a big deal for you maybe. But I work in many different languages in a day. Switching IDE's/editors is a context switch I shouldn't have to make. Go is one small step in that direction.

You don't see an official recommendation because it's not necessary. Pretty much anything you use is going to have comparable functionality due to the work of the go team. Which is how I know that the Go team cares about tooling.


>Pretty much anything you use is going to have comparable functionality due to the work of the go team.

Even so you force every new developer to look around to find whatever he wants, which makes getting started more difficult.

Lets just say that I am a fan of the IntelliJ platform. Which plugin would I install to use with Go?


For the record I don't think you deserve to be downvoted like this. You stated a valid opinion. Go is not meeting a need you have and thus the value proposition for you is not the same as mine. This appears to be a case of people downvoting because they disagree not due to the quality of your comment.


Thanks, but don't worry. I should have known better than attacking peoples choice of editors.


I tried to argue this five months ago when Go 1.4 was released:

https://news.ycombinator.com/item?id=8733705

I was severely downvoted and did not get many who agreed with me.


They did a lot of research on the "internal" folder name and after downloading every github repo that contained go code, they found only a handful of repos that used a folder called internal. Don't think they went into that blind and just assumed no one used the name.


Many "internal" code bases don't reside on GitHub or are marked as "private". I do like Go lang, but some of their decisions are weird.


> The problem with Go is that, while the language and compiler are excellent, Google doesn't a lot care about tooling & ecosystem.

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


"[Go] is a great [ecosystem], lacking only a decent [programming language."


>Stuff like declaring a folder named "internal" special where it wasn't before.

Where can I read more about this?


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.

.


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


(I regularly downvote comments that are negative, and leave comments explaining why I found the comment to be negative).

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.


Well, I get quite the opposite impression of condescending with them hanging around HN and golang nuts discussing language issues. And I'm actually fine with them making the decisions in the end. Go wouldnt be as clear and productive as it is today if every request for a feature would find it's way into the language in some half-hearted manner.


Isn't comment-driven code generation kind of the definition of a "feature request implemented in a half-hearted manner"? People asked for generics and got this. It seems like the kind of suggestion most language designers would throw out as unelegant.

If the language is so conservative as people claim, it should have neither macros/generics nor any of these pseudo-macro-generic-y half-measures.


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

As long as it aligns 100% with the bizarro ideas of the core team regarding comment pragmas, code generation, vendoring, generics, etc.


My apologies if I sounded a bit rough. I know and like your conservative approach and respect your work. I just think that's not a good feature, at all. Because once you start adding pragmas in comments, where does it stop? I'm a bit emotional about it because I love Go,I use it everyday and have been successful with it. If i didn't I wouldn't be writing about it.


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


Fixing the lack of generics is not the intent of supporting a standard way to do code generation. The intent is to allow for things like generating code from protobuf specs and yacc. In fact, there was even debate against adding go:generate because they were afraid people would use it to get something like generics. To say it is for generics is to grossly mischaracterize the feature.


Given that this is the only way Go provides to gain access to generic-like behavior, you shouldn't be surprised when people use it that way, and the intent of the team is quite irrelevant.


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


It's a project were all decisions taken by the core 3-4 person team are final and absolute. Open-source != bazaar.


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.


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


I'd argue that making the changes you desire in an open-source project and forking the project is immeasurably more productive than complaining about it on HN. (IMHO)

There are many cases where project forks become more popular than the original project itself.


This is an odd comment considering the entire point of this discussion is that a bad choice has been foisted on the project and criticism flatly rejected by the core team. Why do you believe a "better solution" would be accepted?


You have a very naïve view of the world and an unrealistic conception of what open source is.


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


The issue that I, and apparently many other people, have is that this is just an unnecessary potential confusion. Why not use another symbol for directives, instead of overloading comments? Why create the potential for confusion - not everyone that will work with Go is going to be deep in the ecosystem - for example they might be using an editor that mischaracterises the line as a comment. Why create this potential for confusion instead of just using a new symbol ($$, @@, %%, whatever). It would be much clearer to the casual reader that this is something that will have an impact at the tool level.


Also 'cgo' comments which are fairly old. See: https://golang.org/cmd/cgo/

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.


I think this was a bad decision. I think you would agree as soon a tool emerges that follows your example and uses

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


If the add "//Todo:" as syntax, many projects would be screwed. Abusing comments for anything else is not good.


Maybe I have missed the point, but your post sounds like you think Merkur disagrees. I think that you are actually agreeing with the GP (https://news.ycombinator.com/item?id=9523335), which says that:

> I think this was a bad decision. I think you would agree as soon [as] a tool ... uses

    > //todo: bar
(i.e., that the `//todo:` syntax would unambiguously demonstrate the bad-ness of the decision).


If this has to reside in comments, will the old directives be updated with aliases for the new convention? So the old ones can be kept around for backwards compatibility (maybe with a warning) but codebases could still be updated to be consistent.

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.


And there's

    //line path/to/file:linenumber
and

    //go:noescape


Reminds me of typescript

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


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


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.


don't forget

    //go:nosplit
too


And go:linkname, go:nointerface, and go:nowritebarrier You can see the lexer for these here: https://github.com/golang/go/blob/88c08b06b97296e41fc3069f4a...


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.


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


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.


Fully agree. I love Go and use it for anything related to servers or the web, but doing anything with comments besides just letting them be comments, is just braindead.


They aren't used by the compiler at all.


    //#cgo
    //go:nosplit
    //go:noescpae
are all used by the compiler in one way or another


nosplit and noescape are internal details which are implementation specific.


All of these are implementation specific. That's one reason they're in comments, and not listed in the language spec.


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.


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.


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


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


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.


That's a valid thing to do in C++ because the language doesn't support alternatives. And you can't really expect it to, because C++ has tried various things over the years that make this much harder to add ex-post facto. However, it's worth noting that using such tooling in C++ can cause more problems than it solves if you aren't careful. This is just one of the ways C++ is showing its age.

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.


As long as you're making it seem like C / C++ code, but isn't, and will break if you treat it like C / C++ code, why not actually extend the syntax?

Something like PY_CODE(<blah>), for instance. That way it won't compile unless you run it through the preprocessor.


Interesting. Why don't you use an include file directive there?

    enum_example_t
    {
        #include "example_values.txt"
        EXAMPLE_Max,
    } 
where example_values would have the strings 'EXAMPLE_foo,'? Just wondering.


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


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.


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?


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.


Funny that you mention it, but Rust also checks all code in comments/documentation for validity, and runs test on your comments and catches if any of them fails to compile/return appropriate result.


No it doesn't. Rustdoc examines the "doc" attribute on every item for Markdowk code blocks and checks those. The "doc" attribute can be attached to an item directly, using Rust's general attribute syntax, or using so-called "doc comments" which are visually and lexically distinct from ordinary comments. In the case of single line comments (the preferred style), doc comments have three slashes instead of two; a good IDE or editor mode for Rust will highlight doc comments differently than ordinary ones.


Right, but it's nearly identical to having instructions in comments, like Go does. And while the post I was implying seems to think this isn't a valid use case, I think it is.


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.


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.


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!


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


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


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.


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.


1, 2, and 4 are pretty strong arguments.

I've written a handful of go generate utilities to do everything from CRUD boilerplate to produce Python clients. Generally, I have found the current approach simple enough and don't have any motivation to change. I would like to see more definition in terms of best practices as defined by the core authors (perhaps release a few more of those internal tools). They have done a little to try to coax the community into their way of thinking, but I think we need more. Coming from C/C++, your motives aren't unreasonable, but I also fear the innovation might encourage sprawl well beyond the original concept definition. That restraint is pretty common in the history of the language and a way of thinking that I like.

As with so many that desire generics, maybe the solution is simpler: Go might not be the right language for you.


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


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


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.


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.


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.


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


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!


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.


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.


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

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.


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?


Yes, I like to elaborate. Good code is unambiguous.

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.


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?


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.


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.


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


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?


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


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.


Doesn't Go complain about unused imports ?

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.


Yeah me too, and I can't recall that ever causing an issue with these comment directives.


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 #


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


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.


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?


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.


Yeah you're right, my bad, I vaguely remembered it but it was a framework I was using, not the language itself. Still stupid anyway.


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


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


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


Thanks, didn't know!


No, you can use any program to launch executable scripts that start with #!. The kernel sees that magic number at the beginning of the file, tries to read a program path and arguments, adds the script as the last arg and executes the whole thing.

The various shells are just a subset of the possible programs used.


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


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?


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)


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.


thank you, for beeing open to be convinced :)


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.


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.


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.


Oh don't forget the good old

    // +build !linux
build constraints feature. It's been there since go 1.0 afaik.


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.


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.


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?


Realistically there is no big difference between /// and //go: although the former is well used (Java, C# and, probably more importantly for Golang, jsdocs are written as /). Either would be useful.

But the complaint is about //foobar: and that is just confusing.


no difference - both are misused comments.

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!


None, i just didn't know about //go: :)


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.


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

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


The decision to put type annotations for variables in comments was made specifically for backwards compatibility reasons.

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.

[0] https://www.python.org/dev/peps/pep-3107/


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.


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


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


That may have been a hack based on emacs where you can set various file options with comments like that.


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


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


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.


It was done on Lisp Machines and currently in CCL.


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.


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


//go:fancy

seems more appropriate.


:p -_- very nice


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


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


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




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: