9 ms·
Twelve Go Best Practices
- nine_k 13y agoIf #6 is among best practices, I'm sad. I could take a dynamically-typed language instead. http://talks.golang.org/2013/bestpractices.slide#6 http://talks.golang.org/2013/bestpractices.slide#6
- dscrd 13y agoThey allow dynamically typed methods when you need them. Why does that make you sad?
- nine_k 13y agoLoss of strong typing and runtime type detection is what makes me sad. Well, Go 1 has some of the problems of Java 1: no generics, typecasts from interface{} here and there, simplistic GC. Reasons are probably similar: this all is good enough for version 1, and can later be improved upon.
- kristianp 13y ago"Well, Go 1 has some of the problems of Java 1: no generics, typecasts from interface{} here and there, simplistic GC. Reasons are probably similar: this all is good enough for version 1, and can later be improved upon." Except I doubt we're going to see generics in Go version 2, whenever that may be. The sentiment against it has been pretty strong in the golang-nuts mailing list.
- Ziomislaw 13y agoanything stopping you?
- nknighthb 13y agoif 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 level. By the third my brain is trying to crawl out my eyes and strangle me, even on code that doesn't have a potential exit point at every level.
- dragonwriter 13y ago> 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? Its pretty much the natural naive composition of conditionals. I think eventually most people come to the point where the rightward-marching blocks become irritating and they look for ways to avoid them, and in the case of conditionals where one branch ends in a return there is an easy way to do that, but that particular case (and, thus, the solution) may not be as familiar to people coming from languages where error returns aren't idiomatic (though you do run into it elsewhere, just not as often, so its less likely to result in deep nesting if you don't pay special attention to it.)
- ajanuary 13y agoI normally see a form of it from people that don't like early returns. But if you try to do that with code that explicitly passes pack errors, you end up having to twist the code to avoid early returns. I guess this form pushes all the returns into a list at the bottom, which makes them more comfortable?
- MetaCosm 13y agoPeople don't like early returns because sometimes they return before some basic cleanup / must have function component is run. Normally added by someone unfamiliar with the function accidentally. Go's defer statement makes this much less of an issue, you bind your work piece with your defer piece so that early returns are fine.
- btilly 13y agoHistorically some people were against early returns, loop flow control, and the like as part of structured programming's overreaction to the widespread unstructured use of goto for flow of control. They wanted every body of code, be it a function or a loop, to have one entry point and one exit point. Over time programmers have learned that one entry point, multiple exit points, is OK. But I feel that it is a good habit to flag that with a comment in capital letters so that someone skimming the code can't miss it.
- conroy 13y agoMeta comment: does anyone know what software is used to generate these slides? I've seen a few slide decks in the same format and they're impossible to use on mobile. I'd like to fix that
- dudus 13y agoI believe they use this template: https://code.google.com/p/html5slides/ https://code.google.com/p/html5slides/ But it's outdated. And the new version claims to support mobile. https://code.google.com/p/io-2012-slides/ https://code.google.com/p/io-2012-slides/
- wolf550e 13y agoMaybe this: https://news.ycombinator.com/item?id=6111370 https://news.ycombinator.com/item?id=6111370
- realrocker 13y agoIt has been generated by the Go package: http://godoc.org/code.google.com/p/go.talks/pkg/present http://godoc.org/code.google.com/p/go.talks/pkg/present
- campoy 13y agoHi, I created these slides using code.google.com/p/go.talks You can actually find the source code and the slides in it.
- conroy 13y agoThanks for the link. I'll take a look and see if I can make it work better on mobile.
- jdmichal 13y agoDidn't read, because mouse scroll wheel doesn't work. Honestly, who thinks this stuff is a good idea?
- dragonwriter 13y ago> Didn't read, because mouse scroll wheel doesn't work. You don't need the scroll wheel to navigate the presentation. Click on the right side of the slide to go forward, on the left side to go back. > Honestly, who thinks this stuff is a good idea? People who are making presentations to deliver in an in-person setting where putting them on the web for everyone is a secondary use, not the primary use? I mean, looking at that, it would be a lot better as the visual component of an in-person presentation than it is on its own (though its not without value on its own.)
- freyr 13y agoAlso, you can use the arrow keys to go back and forth through the slides.
- buerkle 13y agoYes all those options work. But why remove a common method of navigation? In addition, the format makes it impossible to search for text within the presentation.
- mbell 13y agoBecause it wasn't 'removed', rather it wasn't 'created'. You seem to be missing that supporting this feature is extra work and not 'built in' to the way the project is constructed. The author didn't sit there and say, well, fuck the wheel, I'll just throw in a line of code here to disable it, just to piss people off.
- stock_toaster 13y agoDoesn't work super well on mobile though.
- alec 13y ago"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.
- gertef 13y agoI'm sort of hoping someone forks Go to provide at least a few single-depth generics like Optional/Maybe, to match Map and Slice.
- rybosome 13y agoIf it had been done at the very beginning, I think it would have been wonderful...but given that legal, idiomatic nil is already out in the wild I think it's too late. Such a shame - in the example of error handling, returning an Option doesn't appreciably increase verbosity: _, err := potentiallyErroringOperation() // with idiomatic nil if err != nil {...} // with monadic Option if err.isDefined() {....} EDIT: fix typo
- dragonwriter 13y agoSomeone's already provided a template processor for/in Go that provides generics. https://github.com/droundy/gotgo https://github.com/droundy/gotgo
- rybosome 13y agoGo 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.
- dragonwriter 13y ago> 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 would assume that everything that hasn't been implemented in Go 1.1 is not implemented because the devleopers of Go "didn't see a place for" it. Now, either not seeing it as more important than the theings that did make it in, or seeing it as trickier to implement and acceptable to do without in 1.x, that's quite valid.
- schoper 13y agoHe starts dropping errors in "Type switch to handle special cases"
- ktt 13y agoInteresting that this snippet: func (g *Gopher) DumpBinary(w io.Writer) error { err := binary.Write(w, binary.LittleEndian, int32(len(g.Name))) if err != nil { return err } _, err = w.Write([]byte(g.Name)) if err != nil { return err } err = binary.Write(w, binary.LittleEndian, g.Age) if err != nil { return err } return binary.Write(w, binary.LittleEndian, g.FurColor) } could be written like this: func (g *Gopher) DumpBinary(w io.Writer) { binary.Write(w, binary.LittleEndian, int32(len(g.Name))) w.Write([]byte(g.Name)) binary.Write(w, binary.LittleEndian, g.Age) binary.Write(w, binary.LittleEndian, g.FurColor) } if the language supported exceptions.
- dragonwriter 13y agoGo supports exceptions (called "panics"). The substantive difference between Go and, e.g., Java with regard to exceptions is that Go builtin and standard library functions panic in a much narrower range of circumstances than Java's standard library. Go seems to prefer that the decision that an error condition is treated as a panic is generally left to user code that is written with more awareness of what is exceptional in the context of the role of that code than standard library code has. So, you could write the code in pretty much exactly the way you propose in Go; you'd just need to write a wrapper function around binary.Write that panics on errors.
- moe 13y agoGo seems to prefer that the decision that an error condition is treated as a panic is generally left to user code that is written with more awareness of what is exceptional in the context of the role of that code than standard library code has. That makes little sense in the context of ioWriters and, frankly, most contexts. How often do you write code where you deliberately want to be oblivious of IO errors?
- dragonwriter 13y ago> How often do you write code where you deliberately want to be oblivious of IO errors? The existence of error returns means that the IO library function "not panicking" and the calling code being "oblivious of IO errors" are not equivalent. I think the motivation for the Go convention of keeping panics internal and reducing to error returns in library APIs minimizing the potential downsides of the way unchecked exceptions are not part of the declared interface of functions and yet have a major effect on control flow. A convention of using panics (which amount to unchecked exceptions) only within logically bounded units is, IMO, a sensible approach to this. (You could do this with checked exceptions, which require additional syntax in declarations. When you already have support multiple valued returns, I don't see that checked exceptions get you much that's worth making signatures more complicated.)
- frou_dh 13y agoSomething that doesn't sit right with me is the use of a "channel of bool" when the receiving goroutine doesn't actually care whether true or false is sent. It muddies the API to force the sender to choose one of two values when all that's really wanted is an amorphous signal. e.g. in http://talks.golang.org/2013/bestpractices.slide#25 http://talks.golang.org/2013/bestpractices.slide#25 , the first case in the select will trip regardless of which value arrives, yet the sender was still made to choose one.
- shurcooL 13y agoA channel may be closed with the built-in function close; the multi-valued assignment form of the receive operator tests whether a channel has been closed. [1] Given that is available, why is the use of a separate bool quit channel preferred? [1] http://golang.org/ref/spec#Channel_types http://golang.org/ref/spec#Channel_types
- dragonwriter 13y agoA quit channel (that is not receive only) can be used to send back a quit message by a goroutine that only has a receive-only view of the main data channel; close() can't be called on a receive-only channel.
- frou_dh 13y agoIn the link, the quit is acknowledged, so one side closing the channel straight off the bat wouldn't allow for that.
- bradfitz 13y agoJust sending "true" as a signal is a convention, but some people prefer something like http://play.golang.org/p/oXapo7R4RX http://play.golang.org/p/oXapo7R4RX
- frou_dh 13y agoCool, I like that. In some ways, it would be nice if there were a friendly alias for struct{} as part of the language, but I suppose it's hard to come up with a good general name for that.
- tomgagnier 13y agoSlide deck is good idea - but does not work with swipe on OS/X - a clue to click on the right side would be nice.
- millstone 13y agoThe 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!
- jamesaguilar 13y agoThirteen: don't try to sort, it's going to be painful if you do. http://golang.org/pkg/sort/ 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.)
- gertef 13y agoProject Lombok for Go would be relative easy, and so nice.
- jamesaguilar 13y agoWow, that's magnificent, although I don't think Go's reflection capabilities are quite sufficient to fix this particular language bug with decorators. But maybe my imagination just isn't sufficient.
- rorrr2 13y agoHoly shit that function adapters example is convoluted. I'd say fewer than 5% of my programmer coworkers would figure out what's going on. func init() { http.HandleFunc("/", errorHandler(betterHandler)) } func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { err := f(w, r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Printf("handling %q: %v", r.RequestURI, err) } } } func betterHandler(w http.ResponseWriter, r *http.Request) error { if err := doThis(); err != nil { return fmt.Errorf("doing this: %v", err) } if err := doThat(); err != nil { return fmt.Errorf("doing that: %v", err) } return nil }
- zeeboo 13y agoLess than 5% of your coworkers understand decorators? I don't want to sound snooty but this is a pretty trivial application of higher order functions.
- rorrr2 13y agoI guess I work a lot with average developers. Not every corp is Google.
- jasonkostempski 13y agoSince you're a developer let's assume it's just that your estimate is way off :) Multiply it by 3 and pad it with an extra 10% or so.
- icebraining 13y agoI have to agree; it's basic stuff even for a Python weenie like me.
- marssaxman 13y agoIt's basic stuff because you're a Python weenie; I don't see much use or discussion of decorators outside the Python world.
- joshuaellinger 13y agoOdd choice of examples... 1. The file I/O makes the case for including exceptions in the language. Specifically, adding one-off types to deal with exceptions is a bug, not a feature. There is a good case against exceptions but that ain't it. 2. On slide 5, it appears to show that you have to use a switch statement on a generic to get polymorphism because the language doesn't support overloading. Again, looks more like a bug than a feature. Also, is the "break;" implicit in Go? At first glance, it looks like a coding error.
- llimllib 13y agoPresumably these are tips for coders, not for language developers. As such, the language has neither generics nor exceptions and the programmer has to deal with that. > is the "break;" implicit in Go? Yes. http://golang.org/doc/effective_go.html#switch http://golang.org/doc/effective_go.html#switch
- bcgraham 13y agoW/r/t #2 - you're not familiar with Go but knew exactly what was going on. That's totally a feature. The language was designed around exactly that kind of reading. "break;" is implicit in Go.
- joshuaellinger 13y agoSure, I spend a decade in C. It's not hard to read. My only problem with using generics in this context is that you can't catch type-conversion errors at compile time. Seems like a step backwards with only downside. I get why exceptions are a double-edge sword. I'm not clear on why undermining compile time type safety is an feature.
- burntsushi 13y ago> I'm not clear on why undermining compile time type safety is an feature. More safety usually requires a more complex type system. Such a type system is usually more expressive and can make more guarantees about your program, which is a pro. But of course, it is also more complex, which is a con.
- hannibalhorn 13y agoThe 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.
- deskamess 13y agoOf all the code in there this part confused me. What exactly is being switched on? It looks like v is being reassigned to the type of v, then the type of v is written out (instead of the value).
- hannibalhorn 13y agoIt's being switched on the type of v (string or other, in this case), though in a more complex case you could easily have several different types. The assignment basically redefines v to be the matched type inside the case statement. You could easily just add a "sv := v.(string)" as the first statement of "case string", then use sv in place of v within that block, but this does read much cleaner. I think it gets more interesting when using several, often complex (struct) types in the same switch statement.
- gertef 13y ago"type" is a magic word in Go, and in that example. It's highly idiomatic -- it's inconsistent with the rest of the language (Using "type" instead of an actual type), but it makes sense once you memorize the idiom. Sort of perlish -- there are two different operations that look basically the same, and the correct one is chosen based on context (in this case, the context is "is there a type name, or "type" literally?) Perhaps it would have been cleaner to use "*" or some other operator symbol instead of the reserved word "type"
- dragonwriter 13y ago> "type" is a magic word in Go, and in that example. Specifically, type switches are a specific syntax construct that look very similar to normal switches, but switched on something that looks like a type assertion with "type" in place of an actual type.
- workhere-io 13y agoUI best practice: Avoid horizontal scrolling.