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

Go's syntax and semantics seem ad-hoc, hard to remember, and inconsistent, but that's because Go was designed from uses cases and experience by prominent thought leaders such as Rob Pike and Ken Thompson, and Google. For example, sometimes you'll get Unicode code points, but sometimes you'll get bytes of UTF-8. The language was designed to give you the right one in the right case. UTF-8 is coupled with the language because it's the most useful choice. Another example is that pointers are automatically dereferenced, but not when you have pointers to pointers, because that's less useful. If any thread runs in an infinite loop that doesn't call built in functions, the entire runtime will freeze. But this is by design. You're meant to do actual useful stuff in your loop such as calling IO functions (which will yield to the scheduler) or calling GOSCHED.

It was designed to compile fast, and compiles faster than most languages and still has near C-speed. It doesn't have a GIL so it has better concurrency (Java style memory model). It has no complicated features like generics, instead you just use type assertions when you need. It also has impeccable tooling.



> If any thread runs in an infinite loop that doesn't call built in functions, the entire runtime will freeze.

That's not entirely true. Go 1.3 introduced pre-emptive scheduling, so now only the most trivial (useless) of infinite loops will hog the scheduler. But if you're doing real CPU-bound work you won't block other goroutines from executing.


Correct, pointless programs like this freeze but that's by design since they're pointless:

    package main
    import "fmt"
    func main() {
      go func() {
        for ;; {}
      }()
      for ;; {
        fmt.Println("still here")
      } 
    }
Even bigger pointless programs also freeze:

    package main
    import "fmt"
    func f(v int) int {
      return v+1
    }
    func g(x int) int {
      if (x > 100) {
        return 1
      }
      return 0
    }
    func main() {
      go func() {
        for ;; {
          if g(f(111)) == 0 {
            break
          }
        }
      }()
      for ;; {
        fmt.Println("still here")
      } 
    } 
This is of course by design, because Go was designed only to support useful programs. The programmer trying to figure out how the concurrency model works may whine that it's inconsistent and he can't figure it out, but that's only granted because threading is hard. Go makes it easier by only supporting useful cases.


>For example, sometimes you'll get Unicode code points, but sometimes you'll get bytes of UTF-8.

This isn't true, you only get code points when you convert to []rune, I'm not aware of any situation where you would magically get codepoints.

>If any thread runs in an infinite loop that doesn't call built in functions, the entire runtime will freeze.

This is not true, since 1.3 all function calls can potentially yield. Also it only happened if you had as many goroutines running infinite loops as you had kernel threads.


If you range on a string, you get runes.

http://play.golang.org/p/CqLnT4m4GI


> Go's syntax and semantics seem ad-hoc, hard to remember, and inconsistent, but that's because Go was designed from uses cases and experience by prominent thought leaders such as Rob Pike and Ken Thompson, and Google. For example, sometimes you'll get Unicode code points, but sometimes you'll get bytes of UTF-8. The language was designed to give you the right one in the right case. UTF-8 is coupled with the language because it's the most useful choice. Another example is that pointers are automatically dereferenced, but not when you have pointers to pointers, because that's less useful.

How about Go's syntax and semantics seem ad-hoc, hard to remember, and inconsistent because _they are_ ad-hoc, hard to remember and inconsistent? What does your thought leader have to do with your genuine opinion?


Any language seems inconsistent and has hard to remember syntax for people who are new to it. Unlike most of other languages, you can learn Go in a weekend and get beyond the newbie problems. There was a great article lately about Go's syntax - http://robnapier.net/go-is-a-shop-built-jig

The crux of the matter is that there are inelegant parts to the language because they are usefully inelegant, and when you're actually writing software, useful is better than elegant.


How are the Go and Java memory models similar?


For example: if you have one thread polling `x` and another thread writing to `x`, there's no guarantee that the polling thread will ever see any updates to `x`.


> It doesn't have a GIL

On platforms like Go and the JVM, the garbage collector acts like a GIL, which is why they'll never replace C/C++.


Most concurrent C programs of a reasonable size eventually have some kind of big global lock. The linux kernel had one for a long time and it took a lot of effort to add more fine grained locking. Similarly most large C programs have a garbage collector of some kind.


most large C programs have a garbage collector of some kind

[citation needed] - the vast majority of Linux software is C or C++ and I can't immediately think of any with GC. It's not normally assumed, everyone does explicit deallocation, possibly ending up writing their own slab or pool allocators.


That's a good insight. Thanks!




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: