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

I think this reflects a lot of the philosophy of Go (and, probably the goals of Google in supporting it). They didn't just want a language that was productive and shiny and new, but a language whose features would actively prevent coders (Google employees in particular) from writing bad code, sometimes even at the cost of brevity and coder convenience.

So in addition to this feature (actively preventing developers from depending on a particular hash map implementation), there are:

1. No implicit type conversions.

2. No assignment/increment operators as expressions (only as statements).

3. No unchecked array dereferences (though this is pretty standard in new languages).

4. You have to go out of your way to do manual locking.

5. A canonical whitespace style, and tools for enforcing it.

etc. Some of these are useful if you're careful, but the language assumes that you're not careful and will mess it up if you try doing something tricky.

This can be annoying, but it also creates this feeling that, if your code compiles, it doesn't have the same kind of hidden problems that, say C++ or Java code usually does, which is a big draw. (If I understand correctly, those are the other two main languages used at Google on the server-side.)



> ...if your code compiles, it doesn't have the same kind of hidden problems...

Except that Golang has the equivalent of C void*, or Java's Object. This is an issue with working with common data structures like Linked Lists or Trees as Go doesn't have generics. The data section of these in go are all interface{}, so they have to be cast to use the data. This cast can cause unexpected behavior if you're not careful.

EDIT: example[0] here. This is a linked list. PushBack takes an interface{}, and the ".Value" is also an interface{}. The ".(int)" and ".(string)" are casts to get the data out. The assignment to 'b' is a runtime error (not compile time). You can get the type using switch statements or reflection, but there are no compile-time checks for common data structures.

[0] http://play.golang.org/p/K6PpnOkOq6


You're blaming a language for a bug in your code.

interface{} is nothing like void* because it's type-safe. interface{} is (type, value) i.e. it remembers the type of the value it contains. void * is just a value.

Your code snippet has a bug because you didn't check the type assertion result. Here's a fixed version: http://play.golang.org/p/vlsXtEmgMs

In C a cast is unsafe because it doesn't tell you if you did something wrong.

In Go, type assertion is safe. It tells you if it succeeded and if you ignore it, it'll panic, informing you that you have tried to perform an illegal operation.

For more see: http://golang.org/ref/spec#Type_assertions


I was partially incorrect. I said "reflection" could look it up, but you can check it during the conversion as you said (from Effective Go[0]). But my original point (before the edit) still holds true. You need to convert any data stored in a common data structure implementations and you don't easily know its type. So you have to track the type of the data in that structure yourself. So if you pass around a tree, linked list, or whatever, it's not clear what the type is of the stored data by the type information.

But you are right, I'm new enough to Go to forget about the 'ok' check on the type conversion. Checking errors on any unsafe operations is really the best way to go. If you are unsure of the type of a structure you are getting, you really should be checking it.

[0] http://golang.org/doc/effective_go.html#interface_conversion...


> 1. No implicit type conversions.

There are implicit type conversions: http://golang.org/ref/spec#Assignability

> 4. You have to go out of your way to do manual locking.

I don't understand what this means. Go certainly does have a model that permits data races.


(...on the server-side?)


... whoops.

Fixed.




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

Search: