Live data from Hacker News

Things about programming I learned with Go

mjk.space

71–80 of 157 posts

Re: Things about programming I learned with Go

#71
post #40

Earlier quoted context omitted.

>especially when the code seems to continue after printing the error (making it a bug, by reporting a warning as an error). Maybe I'm misunderstanding something, but if you call a function and it returns an error, it's your responsibility to ensure that you handle it. Generally you'd assume any data returned by the same call that returned the error is useless (except stuff like EOF, in some cases?).

Yes, exactly. That's what one would assume. I don't understand why a whole language community decided to not handle any errors and instead just bubble them up without filtering, without adding more notifications about the context like log messages, without trying to recover. Why would they expect a user to know their whole dependency tree and all their error messages.

Google C++ style guide states that you should not use exceptions https://google.github.io/styleguide/cppguide.html#Exceptions golang was probably designed by people following those same guidelines ...

Re: Things about programming I learned with Go

#72

Earlier quoted context omitted.

I would have thought Go is easy to hire people for. It's such a simple language and has such a well-designed standard library you can pick it up extremely quickly. I think "anyone can learn it" is one of its main benefits. Compare that to Rust or Haskell for example...

I think the issue is finding people that want to learn it. Systems programmers are turned off because of it's limitations and your average pythonista or rubyist isn't interested in mucking around in type definitions or even thinking about concurrency.

Despite the obvious "Hey this has a GC!" Go is actually surprisingly good as a systems language. You can do pointery stuff, assembly if you need, etc. I've used it for user-space device drivers on Linux (you can easily use it for ioctls and other low level stuff).

I bet you could even write a kernel in Go. I think the only places where it really couldn't go (ha) are microcontrollers.

Edit: yep: https://github.com/jjyr/bootgo

Re: Things about programming I learned with Go

#73

Earlier quoted context omitted.

I would have thought Go is easy to hire people for. It's such a simple language and has such a well-designed standard library you can pick it up extremely quickly. I think "anyone can learn it" is one of its main benefits. Compare that to Rust or Haskell for example...

I think the issue is finding people that want to learn it. Systems programmers are turned off because of it's limitations and your average pythonista or rubyist isn't interested in mucking around in type definitions or even thinking about concurrency.

I don't think your last point is entirely accurate. I've programmed in Python since the mid-90s and Ruby since 2005, and developers in both camps want concurrency. I think this is why Elixir has really taken off amongst Ruby developers. It is similar enough to Ruby that they don't feel lost, but it makes concurrency extremely easy; a lot more so than Go does, in my opinion.

My reasons for dismissing Go are mainly due to the way it handles memory. Concurrency is handled in Go using shared memory, as opposed to Elixir's private memory model, and Go's threads are not guaranteed to politely take turns the way Elixir's are. I also think Go's packaging system is quite flawed.

I also dislike Go's syntax, but that is just a matter of personal taste.

Re: Things about programming I learned with Go

#74
post #50

Earlier quoted context omitted.

That's ... sad. Sum types and product types are simultaneously easier to understand and are more useful to know about than inheritance. Sum types are simply types whose values can be one of several choices - surely that's something a child can reasonably understand! Product types might be a little harder to grok - they're essentially structs - but surely no harder to understand than inheritance and the whole IS_A/HAS…

Inheritance is not a way to express sum types, it's a form of subtyping. A sum type is like a discriminated union, it can only be one thing at a time. Subtyping allows a value to have multiple (related) types simultaneously, which is much more expressive. I suppose you can use one level of single inheritance to emulate a sum type, but you could just as well emulate it with a discriminated union in Go, e.g. a struct w…

I'm finding that wrapping an interface in a struct can be a good technique. However, the interface{} contains a type identifier, so adding another one seems like wasted space. Usually you can compute it using a type switch.

Re: Things about programming I learned with Go

#75

> Thanks to goroutines and channels Go programmers can take a different approach. Instead of using locks to control access to a shared resource, they can simply use channels to pass around its pointer. Then only a goroutine that holds the pointer can use it and make modifications to the shared structure. How does this prevent data races if more than one goroutine holds a pointer to the shard structure and they're run…

It doesn't. I think goroutines make concurrency easier that it is in, say, Java, but Go still passes around state and that is where a lot of the issues with concurrency arise. Concurrency is much easier to deal with in functional languages, where data is transformed via chains of functions, rather than stored in state.

Re: Things about programming I learned with Go

#76
post #69

Earlier quoted context omitted.

A sum type `T = A | B` means that a value of type `T` can be either of type `A` or of type `B`. Such a type is used to express polymorphism. A product type (from "Cartesian product", i.e tuples) `T = A * B` means that a value of type `T` has a component that is of type `A` and another component that is of type `B`. It is used to aggregate parts into a whole. > Yes, I could go and research functional programming langu…

>A sum type `T = A | B` means that a value of type `T` can be either of type `A` or of type `B`. Such a type is used to express polymorphism. Taking this example (in English / pseudocode): Define a class Animal. Define Dog as a subclass of Animal. Define Cat as a subclass of Animal. Case 1) Now if we have a variable a1 that can, at runtime, contain (or refer to) either a Dog or an Animal instance. Case 2) And if we h…

Both. Assuming that you can actually exclude instances of class Cat in case 1 and of Animal in case 2, that is.

In case 1, the actual type of a1 would be Animal | Dog. In case 2, the actual type of a2 would be Dog | Cat. (Either a1 or a2 might be declared with a different type, this is about the values that they can actually hold, according to your stated premises.)

Re: Things about programming I learned with Go

#77
post #20

I'm no Go expert, so the following may just come from having not used it enough. The two things that shocked me out of continuing with Go were exception handling and package management. Exception handling is basically not implemented. Instead the Go developers dediced to add half a step from return codes towards exceptions and work with that. And now the community seems to have decided to just reraise everything that…

I'm about 8 months in to using Go for a few largish projects and I'd say these are probably the two biggest things I still struggle a bit with. (not generics as others seem to obsess about) On errors, I'm really of two minds. In a way, it is a lot like how Java started with checked exceptions, it forced you to deal with the error. But at some point most people decided that was annoying and switched to runtime excepti…

> not generics as others seem to obsess about

One reason people obsess about generics is specifically because of error handling. With generics, you could implement Result and Option types, which make error handling significantly more sane.

Re: Things about programming I learned with Go

#78
post #50

Earlier quoted context omitted.

That's ... sad. Sum types and product types are simultaneously easier to understand and are more useful to know about than inheritance. Sum types are simply types whose values can be one of several choices - surely that's something a child can reasonably understand! Product types might be a little harder to grok - they're essentially structs - but surely no harder to understand than inheritance and the whole IS_A/HAS…

Inheritance is not a way to express sum types, it's a form of subtyping. A sum type is like a discriminated union, it can only be one thing at a time. Subtyping allows a value to have multiple (related) types simultaneously, which is much more expressive. I suppose you can use one level of single inheritance to emulate a sum type, but you could just as well emulate it with a discriminated union in Go, e.g. a struct w…

> Inheritance is not a way to express sum types, it's a form of subtyping.

A distinction without a difference. This is probably most visible in languages like Scala and Kotlin, which implement algebraic data types by way of inheritance.

That inheritance creates a subtyping relationship is irrelevant; there's a similar subtyping relationship between variants (or groups of variants) and the overarching type using a traditional sum type notation as in Haskell or ML. This is most clearly visible in OCaml's polymorphic variants [1, 2].

[1] http://caml.inria.fr/pub/docs/manual-ocaml-400/manual006.htm...

[2] https://stackoverflow.com/questions/16773384/why-does-ocaml-...

Re: Things about programming I learned with Go

#79
post #69

Earlier quoted context omitted.

A sum type `T = A | B` means that a value of type `T` can be either of type `A` or of type `B`. Such a type is used to express polymorphism. A product type (from "Cartesian product", i.e tuples) `T = A * B` means that a value of type `T` has a component that is of type `A` and another component that is of type `B`. It is used to aggregate parts into a whole. > Yes, I could go and research functional programming langu…

>A sum type `T = A | B` means that a value of type `T` can be either of type `A` or of type `B`. Such a type is used to express polymorphism. Taking this example (in English / pseudocode): Define a class Animal. Define Dog as a subclass of Animal. Define Cat as a subclass of Animal. Case 1) Now if we have a variable a1 that can, at runtime, contain (or refer to) either a Dog or an Animal instance. Case 2) And if we h…

I'm not sure if you can really express it in OO. Sum types are used to represent a closed set of variants. Inheritance like that isn't closed.

In languages that have both OO and ML/Haskell-style type systems like Scala, the fact that the set is closed is denoted by the keyword 'sealed'.

example

sealed trait Color

final case object Red extends Color

final case object Green extends Color

Color can only be Red OR Green. In your example you can have an Animal, a Dog, a Cat, and other things can inherit Animal and create more variants.

Re: Things about programming I learned with Go

#80
post #77

Earlier quoted context omitted.

I'm about 8 months in to using Go for a few largish projects and I'd say these are probably the two biggest things I still struggle a bit with. (not generics as others seem to obsess about) On errors, I'm really of two minds. In a way, it is a lot like how Java started with checked exceptions, it forced you to deal with the error. But at some point most people decided that was annoying and switched to runtime excepti…

> not generics as others seem to obsess about One reason people obsess about generics is specifically because of error handling. With generics, you could implement Result and Option types, which make error handling significantly more sane.

You'd need generics and algebraic types to implement Result/Option
Post reply on HN