Live data from Hacker News

Twelve Go Best Practices

talks.golang.org

81–90 of 153 posts

Re: Twelve Go Best Practices

#81
post #73
post #30

Earlier quoted context omitted.

It's just a different (arguably better default) to have to explicitly ignore errors and/or explicitly bubble them up the call chain. You'll always be in control of your code's control flow that way. You'll never have some random library 5 levels beneath your code throw an exception that you didn't know about, causing your function to return prematurely, resulting in your function accidentally leaving some file handle…

What are the problems with checked exceptions that don't apply to go's approach?

Checked exceptions are harder to ignore :-)

    result, _ = someFunc()

Re: Twelve Go Best Practices

#82

The type cast as part of the switch is really cool, I hadn't seen that before. switch v := v.(type) { case string: w.Write(int32(len(v))) w.Write([]byte(v)) default: w.err = binary.Write(w.w, binary.LittleEndian, v) } Great way to alter control flow based on the type, without a ton of ugly casts cluttering things up.

It's used in Kotlin and Ceylon, but the example above is really just a weak way to make up for the absence of overloading.

The compiler should be making these checks, not the developer.

Re: Twelve Go Best Practices

#83

Thirteen: don't try to sort, it's going to be painful if you do. http://golang.org/pkg/sort/ (See example 1 -- you have to write that for every concrete slice type you want to sort; it's not enough to write it once. And god help you if you also want to sort other collection types.)

Project Lombok for Go would be relative easy, and so nice.

Re: Twelve Go Best Practices

#84
post #20
post #12

Earlier quoted context omitted.

Even the correct version is not that good. The multiple checks on nil is an obvious pattern and as such should be abstracted away. Haskell does it with Maybe but as long as you have function as first class object, it should be doable. Like in Python, Ruby, etc.

The very next slide cleans it up using a "utility type" which reminds me of the "monadic" Haskell solution.

No way, the next slide is the very definition of evil unmaintainable code.

Go through what is happening quickly:

    bw := &binWriter{w: w}
    bw.Write(int32(len(g.Name)))
    bw.Write([]byte(g.Name))
    bw.Write(g.Age)
    bw.Write(g.FurColor)
    return bw.err
If an error happens on L2, we will still run writes L3-L5. Why is this bad? Because in the future, we might come in and add logic after the writes complete. We have to make sure to do a check against the error or we will run this logic even if the write did not work. This is an incredibly easy trap to fall into.

I'd go as far as to call that an anti-pattern - you are hiding the control flow in non-obvious ways.

Re: Twelve Go Best Practices

#85

Slide deck is good idea - but does not work with swipe on OS/X - a clue to click on the right side would be nice.

The interface is quite bad. I was able to scroll right to see a total of three slides, with no indication that there were any others. I thought that was the end!

I tried hitting space, and another slide scrolled in! But I wasn't done reading, so I hit shift-space, which is the common idiom to reverse the direction of space. But it scrolled in the same direction. Now I'm two slides behind. After some more thrashing, I found that I could use the arrow keys to navigate. Delete also goes back.

Please don't make me use trial and error to figure out your UIs, Google!

Re: Twelve Go Best Practices

#86
post #80

if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…

Short circuit returns are the devil - they make it much harder to factor out part of a function into a smaller function. A function should have one entry point and one exit point; that's the whole point of structured programming. If you're going to return from some random point in the middle of your function you might as well be using goto. (Of course, good programming languages provide a better solution than pyramid…

> Short circuit returns are the devil

vi!

Naïve, absolutist positions in areas of long-standing debate between programmers of great experience and the highest imaginable competence just makes you look ridiculous.

Re: Twelve Go Best Practices

#87
post #73
post #30

Earlier quoted context omitted.

It's just a different (arguably better default) to have to explicitly ignore errors and/or explicitly bubble them up the call chain. You'll always be in control of your code's control flow that way. You'll never have some random library 5 levels beneath your code throw an exception that you didn't know about, causing your function to return prematurely, resulting in your function accidentally leaving some file handle…

What are the problems with checked exceptions that don't apply to go's approach?

I have general issues exceptions. I've seen too many developers use exceptions in place of conditionals, and in the worst abuses, use exceptions as some hacked form of GOTO that lets them jump to different points of execution within their call stack.

They're just a little too easy to abuse and are often used for non-exceptional cases. So while checked exceptions improve on exceptions, they are still exceptions at the end of the day.

Re: Twelve Go Best Practices

#88
post #80

if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…

Short circuit returns are the devil - they make it much harder to factor out part of a function into a smaller function. A function should have one entry point and one exit point; that's the whole point of structured programming. If you're going to return from some random point in the middle of your function you might as well be using goto. (Of course, good programming languages provide a better solution than pyramid…

> A function should have one entry point and one exit point; that's the whole point of structured programming.

[citation needed]

Re: Twelve Go Best Practices

#89

The type cast as part of the switch is really cool, I hadn't seen that before. switch v := v.(type) { case string: w.Write(int32(len(v))) w.Write([]byte(v)) default: w.err = binary.Write(w.w, binary.LittleEndian, v) } Great way to alter control flow based on the type, without a ton of ugly casts cluttering things up.

This is why I love pattern matching in languages that support it - typing is just one of the things on which they can switch. As the Scala website puts it (paraphrasing), "Pattern matching is switch on steroids!"

Here is how you would return all leaf values in a binary tree in Scala:

    case class Node
    case class Fork(left: Node, right: Node) extends Node
    case class Leaf(value: Int) extends Node

    def getValues(node: Node): List[Int] = node match {
    	    case f: Fork => getValues(f.left) ++ getValues(f.right)
	    case l: Leaf => List(l.value)
    }
EDIT: Would actually be more idiomatic in Scala to extract the values from the case classes rather than just matching on type...yet another wonderful feature of pattern matching. Coded as follows:

    def getValues(node: Node): List[Int] = node match {
	    case Fork(left, right) => getValues(left) ++ getValues(right)
	    case Leaf(value) => List(value)
    }

Re: Twelve Go Best Practices

#90
post #10

"Deploy one-off utility types for simpler code" can be called a monad or Optional. I wonder if the language developers will add more formal support for that; it looks impossible to add Optional as a library due to lack of user-configurable generics.

Go occupies an interesting space. In my mind, I see it as competing simultaneously with C and Python. I suppose that the developers didn't see a place for an Optional type within that realm. I have to admit, I think it's a shame; huge proponent of non-nullability here.

Especially given that with Go's lightweight lambda syntax a functor type would be easy to work with, I'm disappointed with its exclusion.

Post reply on HN