Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Rob Pike's Go FAQ says that this is one of their favorite features about Go, and I agree; it's how I've been writing C code since 1995. So, I mean, if conformance to my C programming style guide matters, YOU LOSE THE ARGUMENT! :)

I'd also contend that no language makes changing the visibility of a variable completely painless. You're fixating on the one case where you can change the token "private" to "public" and write new client code for a class. But you're ignoring public->private, which is a breaking change no matter what syntax you use; you're also ignoring the fact that moving a variable out of or into a class (for instance with class statics) is breaking no matter what you do.

As this article points out, the major win for simply using case to signal this is that the language gets to dispense with fussiness about where variables are; you can just put them in packages when they make sense.

It's all tradeoffs, of course. It's certainly your prerogative to be annoyed by design decisions in Go! I'm extremely annoyed by the import use requirement and refuse to not be annoyed by it no matter how many times Rob Pike and Russ Cox say it prevents bugs.



If I'm fixated on changing private -> public, that's because it's a common case. I doubt I'm alone with a programming approach of "start with everything private and expose public behavior only as necessary".

More philosophically, I have to wonder what the benefit of this capitalization scheme is. Just to avoid typing 'public'? Hardly seems worthwhile. To make it obvious when reading code? This is the same argument for hungarian notation, which even Redmond has abandoned. IDEs for static languages like Go are perfectly capable of presenting identifiers appropriately - if indeed public/private is really what you want to call attention to.

I admit that I've not done more than dabble in Go, but I'm somewhat skeptical of this last point. Of all the IDEs I have used for various static languages, I have yet to see any that visually distinguish public vs private identifiers. If calling attention to this distinction was so important that it should be built into the language, I would expect it to be common practice in IDE formatting already.


The two major virtues of case-based visibility:

1. It creates a coherent syntax for making names visible that works both for member variables and package variables; you don't ever have to wonder how to expose something, because you always do it just by making the name uppercase.

2. It allows readers to see at a glance without thinking whether a value is public --- it's public if it's a proper name.

In practice, Go struct definitions are extremely succinct, almost (at first) to a fault, because of decisions like this that eliminate syntax from the language. Compare a Go package to an equivalently functional Java package to see what I mean.


Please convince me this is a good idea.

#1 does not seem to be a real issue. Most similar languages have the common, popularly understood, and easily-remembered keyword "public". Whereas capitalization is an exotic special rule that must be learned. If "you don't ever have to wonder how to expose something" is an important measure, I think Go is at a disadvantage here - especially if you want your code to be read by neophytes.

#2 is the argument for hungarian notation. Why is it important to visually distinguish public/private as opposed to, say, local vs member variable? I point this out because IDEs have a long history of visually distinguishing local vs member variables and some programmers even use naming prefixes like '_' or 'm_'. Yet I've never seen an IDE highlight members based on visibility. Given this backdrop, it's certainly not obvious that visibility requires such an important visual reference. And why shouldn't the IDE be responsible for this decision? Counterarguments that programming languages should be designed for 80-col amber VT100s sound pretty wacky in 2013.

Regarding terseness of the language, I'm not convinced. Without exceptions, Go adds an ton of "if error then return error" boilerplate to practically every function call. This is a lot more typing than adding 'public' to struct members.


I think you have to look at this in the context of the whole language. Go doesn't just not have a "public" keyword. It also doesn't have classes. The way Go structures code is optimized to maximize code reuse while minimizing declarative syntax. So Go has an integrated package system (unlike C++) because that helps you build modules of code that can easily be used across projects, but doesn't have inheritance (unlike C++) because that is a feature that is less about reusing code and more about modeling systems.

I'm sure you've had the experience of working with libraries in other languages where the designer couldn't or didn't make up their mind about whether to expose capabilities as free functions or classes that needed instantiation, or, worse, exposed factories and singletons to get around their discomfort with simple functions.

Go sidesteps this problem. I found it helpful to think of it not as removing the "public" keyword from struct defs, but as creating a mechanism to "promote" functions and variables in packages --- something that would feel very shady in C++, but doesn't in Go. As a result, a lot of packages do The Simplest Thing That Could Possibly Work and just expose simple functions. The result is usually refreshingly clear.

I agree with you about error handling; Go's error handling makes its source code (though not its library interfaces) fussy and hard to read.


Some thoughts in defense of Go's use of capitalization. First of all, public/private are used in languages with classes. It would be misleading in Go, since visibility is at the package level.

Second, if Go didn't use capitalization and wanted to keep package level visibility (which I will strongly argue is the Right Thing), there would be choice of having both private and public as keywords and requiring one of the pair to be put before before all constants, package level variables, type declarations, struct members, functions, and methods -- creating an immense amount of noise -- or to have one of the two and make the other one the default. Probably it would make more sense to have everything private by default and public only when prefixed with public… But it would be really ugly and inconsistent.

Now it might be possible to get around this with some other convention. Maybe it could be like Python, where everything is public by default but private if it starts with _. Or it could use a different, shorter keyword like 'p' so there's less noise overall…

But I think that once you make the decision to have package level visibility, case is the most efficient way of expressing it.


1. Most languages allow multiple public modifiers, which can make humorously confusing experiences where you think something is private, but in reality, it's in the second public block.

In denser structures, particularly dense all-lowercase structures, this is easy to miss.


Most programming languages use these conventions informally. For example:

Javascript - always capitalize classes

Python - underscore before private properties

C# - underscore in front of class level private properties

Python upgraded the whitespace convention to meaningful whitespace, why shouldn't Go upgrade the naming convention?


Python - everything is public, so a convention is required to make developers distinguish between public and intended-private-but-still-public (e.g. do not touch).

C# - I don't really know what's common practice in C#, but without a really good reason placing underscore in front of private properties would be really, really stupid.

On Python again - I used Python everyday for the last 3 years and I hate the whitespace convention. It's not because I have to use significant whitespace, but this syntax is the number one reason for why the language never got anonymous code-blocks. And I love the lightweight syntax, but looking at other lightweight languages, working with significant whitespace is just not worth it if it disallows such a useful and common feature.


If I'm not mistaken Guido has been thinking about anonymous code blocks as a possible purpose of the with statement but he was persuaded not to do such a thing as it won't fit into python's core concept TOOWTDI (there is only one way to do it). Significant whitespace by no means implies lack of anonymous blocks, they will just look a bit differently. Look at CoffeeScript if you want to see an example.


Actually, I find public->private is not a breaking change, because before I do a 'public->private' change, I first remove all the public calls. Therefore, all I have left to do is to check the in-class calls.


That's great for you, but I suppose you've never published a module on CPAN, a ruby gem, a Python... egg (man, that's a weird convention). As soon as someone else depends on your module - and Go is very modular, this behavior is encouraged - suddenly it's an exercise in putting fluids back into containers, or whatever they say.




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

Search: