17 ms·
Go best practices, six years in
- krat0sprakhar 10y ago> That advice still holds today: vendoring is still the solution to dependency management for binaries. This might be a stupid question, but can someone explain to me what this means? Thanks!
- sudhirj 10y agoTo vendor a dependency is to store a copy of all the source code you're trying to use inside your project itself. That way, when you compile your project, you also compile the code it depends on. Updating code you depend on is a semi-manual process - you choose to copy the latest version of the code you depend on into your project again. This is contrast to stacks like Java, where I can give you a pre-compiled JAR file that you can link your code to.
- fpoling 10y agoI have found that using git-subrepo is a great help with vendoring as single git subrepo pull --all is enough to update all dependencies.
- fludlight 10y agoIs this different from statically linked libraries (as opposed to dynamically linked)?
- NateDad 10y agoThis is about code, not libraries. Vendoring the code means copying it into your own repo... that way you're guaranteed that everyone who builds your project is building the exact same code, and if one of the third party repos disappears, your project doesn't all of a sudden fail to compile.
- bitwize 10y ago"Vendoring" means maintaining local copies of third-party libraries and other dependencies in your local repo so exactly what you depend on is a part of your internal history. Git provides ways of doing this easily, such as subtrees.
- bboreham 10y agoJust to add: the name comes from the convention of storing all those dependencies in a subdirectory named "vendor".
- jud_white 10y agoA point of clarification for anyone skimming the original article: > Top Tip — Libraries should never vendor their dependencies. Peter goes on to clarify: > You can carve out an exception for yourself if your library has hermetically sealed its dependencies, so that none of them escape to the exported (public) API layer. No dependent types referenced in any exported functions, method signatures, structures—anything. I think this is the way to go if you're writing a library which has its own dependencies. You get a repeatable build and free yourself to change which dependencies you rely on without impacting users of your package. There are exceptions, such as if your dependency has an init which only makes sense to run once. Loggers come to mind, where the setup should be determined by the main package. The f.Logger point in the article is friendlier to users of your package than just using log.Printf, and frees you from having to vendor logrus, for example, if you want to support structured logging.
- wtbob 10y agoGood article on the whole, but I have a few quibbles: > If your repo foo is primarily a binary, put your library code in a lib/ subdir, and call it package foo. IMHO, that's just ugly, uglier than foo/foo or foo/foolib or foo/libfoo. I also think that anything which has commands other than a single-command project which will always be a single-command project (there are fewer of these than one might think …) should put all commands, even a single one, in cmd/. I think that inline config objects should be used with useful zero values to try to emulate Lisp's or Python's keyword arguments: if one always needs to provide a value for each config object member, then just use arguments after all. I think a testing library can be a great addition, since it can turn a three-line if check into a one-line assertion.
- curun1r 10y ago> IMHO, that's just ugly, uglier than foo/foo or foo/foolib or foo/libfoo. > I also think that anything which has commands other than a single-command project which will always be a single-command project (there are fewer of these than one might think …) should put all commands, even a single one, in cmd/. It's this kind of inflexibility in the directory structure of ones repo that really turned me off of Go. It's such a trivial thing, and yet the fact that Go lacks a level of indirection (package.json, Cargo.toml, pom.xml, etc) to map a chosen directory structure to the standard build tooling causes problems that get really annoying. For instance, there's a ton of Go repositories out there that are not go gettable because the author wanted to put source code under a src directory and hacked that together using make. And good luck with organizing any repository that contains multiple languages where go is one of them...go's "code lives at the repository root" doesn't play well with others. It all makes me sad since Go's decentralized dependency management (i.e. go get being able to pull/build based on a meta tag) is brilliant and I always hate having to rely on a single, centralized repository to deal with dependencies.
- wtbob 10y ago> For instance, there's a ton of Go repositories out there that are not go gettable because the author wanted to put source code under a src directory and hacked that together using make. Are there? If someone's that ignorant of the language, I don't think I'd want to run something written by him … > And good luck with organizing any repository that contains multiple languages where go is one of them...go's "code lives at the repository root" doesn't play well with others. I've actually built libraries which involved both Go & Python without a problem.
- dineshp2 10y agoSlightly tangential, but, could someone share their experience using Go specifically for building websites? How does Go (including Go frameworks specifically geared towards web development) compare in terms of performance, ease of development with RoR, Laravel? Is building websites using Go a good use case or is Go better suited for building high performance microservices?
- tyingq 10y ago>>How does Go ... compare in terms of performance, ease of development with RoR, Laravel? The available web frameworks for Go are more comparable to microframeworks like flask. If comparing directly to RoR or Laraval, you may find some gaps. Not that they can't be solved, but there's less available out of the box. Things like: - multiple file upload - session handling without cookies - built in support for a variety of authentication types and backends The communities are also significantly smaller, so there's less experience to draw on. Not to say you can't build websites just fine with golang, but it's doesn't seem to be a strong suit at the moment.
- Thaxll 10y agoGo is pretty good for anything backend related.
- eternalban 10y agoNo, that is definitely not correct, unless your "anything" is merely that which is fully defined & composed at compile time. (And yes, you can go the IPC route to introduce dynamism that you get out of the box from a VM based language. But here is the classic case of the Go [tail] wagging the architecture [dog]..) [edit: correct tail endian]
- asimuvPR 10y agoMy experience over the years is that Go serves a specific niche ver well. The niche being boring long running services that do simple tasks in unison with other services. It's better to see it as a language wi th which you can build little self contained machines that work well together. I have a system made up of such little machines and it quietly works away at some low end server.
- themartorana 10y agoThe article sort of glosses over IntelliJ with the golang plugin as an "other" IDE, but it's best in class hands down. At one point in my past I had sworn off of Java-based IDEs, and used Sublime Text for years with primarily Python and Go. Something convinced me to try Go in IntelliJ, and really it's fantastic. It also covers "important-to-me" features the author mentions. I haven't tried VSCode yet, but have tried all the others listed. IntelliJ is fantastic for Go.
- sagichmal 10y agoIn my experience most Go developers seem to favor a terminal-heavy workflow, sometimes frequently shutting down and re-opening their editors in new paths and projects. The barebones simplicity of Go-the-language seems to be a nice match to this workflow. It's a different thing altogether to how large IDEs like IntelliJ expect you to work: opening up a project and staying in the IDE for a long period of time. Both approaches are totally valid, of course, but I suspect Go developers are biased toward lighter-weight editors.
- nedsma 10y agoI concur. Go syntax is dead simple and even the most basic tools like https://play.golang.org/ https://play.golang.org/ can be used without hesitation for some quick and dirt POCs. In the discovery mode, when you're learning a new library, any tool that supports code completion and provides documentation links is nice to have.
- deleted 10y ago[deleted]
- alexellisuk 10y agoAfter working with .NET/Java/Node.js/Ruby/Python etc the move to Go involved a larger investment in time. I found this really informative and it's great to have the learnings condensed down.
- nedsma 10y agoCheck out YouTube conf. talks from the same author, where he shared his experience developing services in Go, while working at SoundCloud. Also, very helpful.
- Philipp__ 10y agoCould you please provide the link?
- Hates_ 10y agoI'm assuming they are the ones listed here: https://peter.bourgon.org/talks/ https://peter.bourgon.org/talks/
- nedsma 10y agoYes, thank you, appreciated.
- alexellisuk 10y agoChecking these out now. I use SoundCloud.. cool to hear about their infrastructure. It is a bit weird how you can't see his hands in the shot: http://www.infoq.com/interviews/bourgon-crdt-go http://www.infoq.com/interviews/bourgon-crdt-go
- alexellisuk 10y agoI have run a coding-dojo type project internally at work at ADP. We had two PRs in Go, so while we are on this topic, are there any improvements that can be made to the Go submissions? Does anyone want to submit a best-practice Go solution? https://github.com/alexellis/xservedbyfinder https://github.com/alexellis/xservedbyfinder
- alblue 10y agoIt was a great talk at QCon London earlier this year - the video is due to be published towards the end of next month. I'll try and come back to this thread when it is with the URL. (Disclaimer: I was the track host for Perer's talk)
- dllthomas 10y ago"those parameters should be part of type constructors" I'm not sure if this is a nit, a misunderstanding on my part, or a difference in terminology, but I think what is meant here is "value constructors" (or more commonly, just "constructors"). As I understand the term, "type constructors" construct types.
- sagichmal 10y agoWell, there are no type constructors in that sense in Go.
- MereInterest 10y ago> Only func main has the right to decide the flags that will be available to the user. This one applies to every language. I was working with a python package that decided that, since `sys.argv` was available from anywhere, it should parse `sys.argv` to configure its own behavior. For a long time, their suggestion was to first parse `sys.argv` yourself, then to modify it before going into the library.
- striking 10y agoReminds me of when systemd parsed the kernel command line for the kernel debug parameter, making life hell for kernel devs. It was so ridiculous, someone ended up sending in a patch for the kernel to modify the command line once it had been parsed to remove the debug parameter. https://lkml.org/lkml/2014/4/2/415 https://lkml.org/lkml/2014/4/2/415
- bbrazil 10y agoThis defeats the purpose of a good flags library though. Where flags shine is when you've some obscure tunable deep in the dependency tree that you need to tweak (particularly in an emergency). Plumbing through potentially thousands of flags through to main is nonsensical in that scenario.
- dlor 10y agoThe flag libraries I've used always make this easy, but the problem comes in when you try to reuse that dependency in another binary as a library. Maybe you've seen a better flags library than I have, though.
- bbrazil 10y agoNo, the flags libraries I've used had exactly that issue. When that came up what you'd do then is refactor that to be a class parameter or config option or whatever (and we'd usually ask that the flag be kept in some form). Until then though you get the benefits of a quick and easy way to both expose and use tunables, which is much better than not having it at all.
- nvarsj 10y agoThe stages of go enlightenment: 1. Holy crap, this is like coding in early Java days, what the heck were the language designers smoking?! They just ignored everything! Where's my testing framework! DI?! Build system, dependency management?! WTF. 2. Holy crap, this is like coding in the early Java days! This is awesome! I can understand all golang code I read! Everything is so simple and easy. I finally get "less is more", and "worse is better"! 3. (Many months later) Oh god, I'm getting so sick of writing this test assertion in 4 lines over and over, and writing 100s of lines of mock structs. My tests are 5% substance and 95% setup. Okay let's write a junit/mockito assertion library. Oh crap, I'm having to manually wire everything everywhere and it's such a pain. Let's write a DI library. Ugh my project is getting too big and `go get` just doesn't cut it - time to use a dependency management library. Ugh, makefiles only go so far, time to write a build tool. Ugh code generation and metacoding is nonexistent, let's write our own code generation tool so we don't have to hand build 100s of types. ETC. 4. (Distant future) As golang's stubborn designers finally accept some flaws in their original thinking, they add features to make the language look a lot like another widely used language at the Googplex. Mission accomplished? P.S. This is somewhat tongue in cheek - I do enjoy using golang day to day. It is a refreshing change :).
- RyanZAG 10y agoIt will get extremely meta when golang's infrastructure gets good enough for other languages to want to use. Then they'll split it out into a 'GoVM', or I guess 'GoRT', and then you'll have a 'GoVM' competing with the JVM...
- askyourmother 10y agoAppreciate it was written as tongue in cheek, but I am glad that today a developer can start with Go, test, write code, build, deploy all with Go, whereas nearly every other ecosystem requires additional tools, often external competing tools. Then life becomes about having to learn whole new toolbekt before even coding. Go still keeps it lean, and is great. The fact it does not have hipster dev approved status is also an added bonus. The minute we see a bloated testing suite with yet another DSL, for Go, we are in trouble.
- pred_ 10y agoThe site blocks Tor users; ugh.
- dlsniper 10y agoTry a different exit node, the website uses Cloudflare so if you could access HN you should be able to access that one as well.
- cyphar 10y agoTor creates new routes every X minutes (usually 15). It also uses a different route for every IP it routes to. So they'll always go through a different exit node.
- dllthomas 10y ago> No statements go by where the object is in an intermediate, invalid state. This seems kind of misleading. Per my understanding of Go, omitted fields in a struct initialization are defaulted not reported as errors. So you're equally likely to be passing invalid state, in the two situations. One pattern I like in Haskell, for this kind of thing, is to define a defaultConfig value that contains typical defaults and which can then be tweaked as desired. One big advantage this has is that when some functionality is made newly configurable, you set the default to be the old behavior and existing code continues to work correctly unmodified without any additional effort.
- sagichmal 10y agoHopefully you'll combine that idiom with "make the zero value useful" so that omitted fields still give valid behavior.
- dllthomas 10y agoReading on, I see that. It still breaks down when a zero value is meaningful for a configuration parameter, but means something different than what was done before the parameter was configurable. I think that's probably not super often. In light of all this, I still don't really see what harm we're avoiding by preferring the inlined struct initialization. I do agree it looks a little prettier, but the article seems to give it a greater import.
- transfire 10y agoWhat you need is... a [goat](https://github.com/mediocregopher/goat https://github.com/mediocregopher/goat)
- hesdeadjim 10y agoLibraries using log.Printf are incredibly tough to work with in a production environment if you want anything more interesting than looking at stderr. Libraries that let you provide a logger API at time of construction are better than log.Printf, but they still fail at letting you include contextual information inside method calls. We inject a logging interface into all our methods that take a context.Context object [1]. This allows us to push contextual information onto the stack of context objects, and then when we log we can do it at the point of failure and have access to an immense amount of useful information. Check the attached gist to see an example of how this works in practice [2]. Given that the context library originated out of Google and is now part of the stdlib in 1.7, I would love to see other libraries embrace it instead of relying on much less flexible solutions. [1] https://godoc.org/golang.org/x/net/context https://godoc.org/golang.org/x/net/context [2] https://gist.github.com/justonia/f81eead323d2b23eca1c485ed8e5db5d https://gist.github.com/justonia/f81eead323d2b23eca1c485ed8e...
- kinkdr 10y agoLooks a lot like a language designed by a committee, but I generally like it. I don't love it, like I love Python, but it does its job and it is fast. What I really like is the defer(), the channels(having the option for asynchronous channels would be awesome), the go routines(async callback hell is getting old). What I find completely awkward however is the enforced first letter capitalization(don't tell me how to live my life, go!), the interface{}, and the GC.
- calcifer 10y agoI get - and agree with - the complaints about interface{}, but what's wrong with the GC?
- kinkdr 10y agoNo control over it. It will run when it decides to run, stalling my app.
- kinkdr 10y agoAnd how could I forget, the multiple return values. Give me tuples, Go, don't give me multiple return values!