io.Copy(dst io.Writer, src io.Reader)
It reads data from reader and writes to writer... simple. Now what makes this little function so darn useful is it takes anything fulfilling its interfaces (io.Writer and io.Reader). The first way you will probably use it will be to copy between some stream and a file without having to eat up all the memory to store the buffer (not using ioutil.ReadAll for example)... but then you realize you can use a gzip compressor on the writer side, or a network socket, or your own code... and io.Copy works with anything that fulfills its interface.
As you build out a complex application, you start by creating your own functions that take advantage of existing interfaces foo.OCR(dst io.Writer, src img.Image). After that you start building out your own interfaces... like a MultiImage interface that has ImageCount and ReadImage methods that returns the count of images and binary data... but then you realize the images could be big, so you make the ReadImage method return an io.Reader... and now you have gone full circle and are using io.Copy to copy imageX from a stack of images to return to your OCR function that will output the data to an io.Writer which you made actually a gzip writer because text compresses well.
Beyond composition -- obviously, the concurrency and messaging is nice and when you need it vital. The other thing that will help make Go "click" is being very "data oriented" in your design... be vicious and minimal: http://youtu.be/rX0ItVEVjHc (great talk on data oriented design) and be absolutely pragmatic, focus on getting shit done, always...
And how is that any different than any language with interfaces? (Besides the implicit thing?).
Imagine a close() interface in Java. There isn't one - but having a try {...} finally { x.close(); } can be very useful sometimes. But having interface graphs made of granular interfaces makes everything slow and causes a lot of complexity when you try to think about your type hierarchy. That's why interfaces always just grow and you can't use them any longer because other classes only implement part of the api. Something usable for all of awt, swing, file handling, random foreign libraries? Unthinkable. Also, adding something in a later release (like CharSequence in 1.4) can have a wide ranging impact and requires you to change a lot of code.
In Go, you just add an interface from the union set of multiple structs api - and you can use it. No matter who wrote those structs. The value is enormous. Think of it as something like dependency injection at compile time.
https://docs.oracle.com/javase/7/docs/api/java/lang/AutoClos...
You can even leave out the finally when you use an autocloseable resource.
//r will be closed no matter what
try(Resource r = getResource()) {
} catch(SomeException e) {
}Known as structural typing and available in most modern languages.
Well, "modern" is an ill-defined concept. As far as I'm aware, structural typing is not really that common, is it? Besides OCaml and Scala, is there any relevant (used outside of academia) language that supports it?
F# also supports it, given its ML linage.
C# tricks with dynamic, although in this case it is dynamic typing, so not really the same thing.
Concepts would have fixed this, but we don't have concepts and maybe never will!
enable_if and type traits are a workaround for the time being.
Concepts lite will definitely be in the next revision.
"Duck typing is similar to but distinct from structural typing. Structural typing is a static typing system that determines type compatibility and equivalence by a type's structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type's structure that is accessed during run time."
So it sounds like "duck typing" is defined in terms of run-time semantics. I guess you might be able to have genuine "compile-time duck typing" in a dependently typed language, which could be a good reason to preserve the distinction.
Otherwise, yes, they are certainly similar.
I've implemented InputStreams from byzantine transport layers in Java that work with the standard library. I don't quite understand what is special about this concept in Go (maybe it's nice for people coming from typeless, messy dynamic languages or nice languages with horribly inflexible and ad-hoc standard libraries like Python and Ruby).
I have used interfaces (or equivalent concepts) in dozens of languages and they always felt like far more of a chore, explicitly using X interface or Y interface, ugly complex declarative specs, etc. Go just makes it painless.
What people like about Go is its mix of features, not some specific one by itself.
If it had Generics that would be another thing.
However, you can wrap an interface{} using container (for example), with type-specific input and output functions, getting back compile-time type-checking. Yes, it is not optimal, and yes, you're still paying the price for type assertions.
If it had Generics that would be another thing.
I would like to see a good solution for this that integrates well with the rest of the language.
I say that because the Go designers, despite having designed a quite mediocre language, suddenly when it comes to generics the want the perfect no-compromises solution or nothing.
Say you have a type that implements the io.Reader, io.Writer, io.Closer and io.Seeker interfaces, eg. an os.File. This type would also automatically implement io.ReadCloser, io.WriteCloser, io.ReadWriter and io.ReadWriteCloser, io.ReadSeeker, io.ReadWriteSeeker, io.ReadWriteSeekerCloser, io.WriteSeeker, io.SeekCloser etc.
I read your comment, but this seems more like A sane standard library with proper interfaces and not a language feature per se (also composition to me sounds like the pattern where you create objects which are composed of other objects but that's not what you mean, right)? What you display here can be done in pretty much any language suporting inheritance (or I'm missing something), so your point is those languages don't have io.Copy out of the box?
This means that many standard types in Go implements either io.Reader and/or io.Writer. That's neat. The implicit interface implementation is definitely a language feature, and the libraries are making good use of it.
(That is not to say, you could not do the same in other languages, but you would have to specify the interface they implement rather than just adding a method with a specific layout.[0])
[0] I am not remembering the right term right now.
Close is a particularly good example. One need only look at C#'s IDisposable to see that it does, in fact, work well. A mock might noop it, another class might close an FD, and yet another might make an RPC call.
I agree that interfaces tend to have fairly narrow family tree. And, by this narrowness, there's little ambiguity about what T GetById(id int) means. As the tree expands, which happens with implicit interfaces, ambiguity is more likely. Nevertheless, there's a fairly large common vocabulary that we'd all largely agree on. Closer, Reader, Writer, Logger, etc. Even in more complex ones, I see little risk of confusion, say, http.ResponseWriter. And, something that I've noticed from Go (which I never did in C# or Java), is the tendency to favor very small interfaces, which ends up being pretty awesome.
That aside, consider that implicit interfaces allow the consumer to define the interface. For example, you create a library that has a concrete struct called MyStruct with a method called DoStuff(). You define no interface because you don't need one.
I, a consumer of your library, need an interface because in some cases I'm using your MyStruct to DoStuff and in other cases, I'm using my own implementation. So I create an interface, define DoStuff(), and BAM!, your structure now implements my interface. I don't have to change your code.
Sure, the workaround is to wrap your structure in my own which implements the interface. But how, in this case, is the implicit interface not a huge win?
Maybe, as you say, it'll screw over people who use it poorly. For everyone else, I see no drawbacks.
Haskell's typeclasses work around this by letting you define "how a type implements an interface" at either the definition of the interface or the definition of the type. (Or, strictly, anywhere else both are in scope - but that gets messy for a few reasons, so it's discouraged and GHC warns about "orphan instances" unless you tell it not to.)
That's not a problem with Go's module system. If someone is using your library, and wants to use your interface in a particular package, that's fine. If they want to use another library, with another interface of the same name in another package, that's also fine.
If they want to use both libraries in the same client package, they'll have to locally rename one or both of the imports.
Here's a container interface. It has a sort() method, which sorts the elements of the container.
Here's a different container interface. It's got a method that tells you what kind of concrete container you have, so you can understand how expensive actions like insert and sort are going to be. But the author was from England, and so called that method "sort".
You can see how that's going to (fail to) work out when you define a "sortable" interface...
Traditional (but even more contrived) examples include "draw" and "fire" doing unexpected things when applied to a gun as opposed to an image or an employee.
First, you really have to split this up into two distinct cases.
The most powerful/useful is when you create an interface in your package for a structure in a different package. It's been years since I've done .NET or Java, but I remember frequently cursing a library developer (often someone at Microsoft or Sun) for exposing a concrete type instead of an interface. In this case, I don't see any downside. Creating a:
type Render interface { Draw() }
And then using my (or someone else's) Gun structure, is no different than using the Gun structure directly and expecting it to render itself to the screen rather than come out of its holster. The interface buys you the level of indirection, but whether you use the interface or the concrete type, it's up to you to know WTF Draw() does.
This first approach is well explained at [1]
In the second case, where a library expects an interface, I agree there's a risk:
// 3rd party package package fastRender
type Drawable interface { Draw() }
func Render(d Drawable) { ... }
// my code: fastRender.Render(new(Gun))
I've lost some degree or type checking. Since my Gun's Draw doesn't explicitly implement fastRender.Drawable, maybe I'm trying to fit a square peg into a round hole. There's nothing the compiler can do to help either.
It sounds a bit like an academic concern to me. Is this something that's actually bitten people in the ass? How is it different than any method that takes primitives? I can pass a []byte of a bitmap to a Music player's Play(data []byte) method...
[1] https://medium.com/@rakyll/interface-pollution-in-go-7d58bcc...
There's also a subtle third case - I import two libraries. One of them defines Drawable, the other has something that looks like it implements Drawable. But it's just happened upon the same signature, and makes different assumptions. Maybe it even says it implements Drawable - but a different Drawable defined in a third library.
As I've said all along, I don't know how often these things are hit in practice. I think so far go development has been comparatively centralized, and so it might be seen less often than it would if it were used everywhere, but that might still be rare enough to not be a problem.
It doesn't seem like a high probability that this would happen on accident, though it might be possible to contrive an example.
I'll have to think about that.
One could possibly force the issue by including an unused function with a deliberately unique name (supports_interface_foo, or maybe a UUID or both) as part of the interface. Can functions added later fill parts of interfaces? If so, this approach would make the situation roughly that of Haskell typeclasses. If not, then this approach makes the situation roughly that of Java interfaces. In either case, it might be appropriate to some pickier interfaces.
You could include the name of the interface as part of the method name, though. But the downside of that approach is, if another interface wants to re-use the same method, things get awkward...
My point was implicit, exceptional simple interfaces are sorta magic. They are effortless, and because they are implicit, there is no harm in creating a 1 function interface (or 10 of them). Because your caller is never going to have to do an ... Implements ThingA, ThingB, ThingC, ThingD, ThingE, Thi... it implicitly supports an interface if it fulfills the signature.
So your interfaces end up being tiny (just what you need) and pervasive. This means the way your system ends up working tends to be far more aligned along interfaces than anything else.
When I speak of composition (in this case the composition of functions) I am speaking of the ability to use functions together rather freely and with little effort. This is a bit hard to explain, but it feels a bit like a modern shell, you can wire together lots of commands (functions), from lots of places that have no awareness of each other with the pipe | operator. In Go, simple, minimalistic interfaces act as the glue and let you compose lots of diverse functions together exceptionally quickly.
I'd say it's a better C, not a better C++ (or Java/C#)
For me, most modern uses of C fall into 3 camps:
+ extreme portability
+ complete, low level resource control
+ foundational libraries
And Go doesn't really qualify for any of these. For the latter 2 largely because of the GC.
I think in practice, that its engineering bent i.e. no frills language and high quality tooling, will more likely see it being used in the server-side application/middleware space. I guess not surprisingly.
So it really is up against Java, Python, Ruby and C++ and is, therefore, interesting in that it isn't trying to compete on lingustic goodies.
Yeah, I agree with your points. Which is a shame really.
The strengths of Go to me seem to be its extensive standard libary and the fact that you don't need to worry about writing elegant code because it's not really an option. That reduced decision making is actually really appealing to me on some level, but it's not enough for me to consider it over what I consider better tools (Haskell, Rust).
I'm currently porting a tiny program a friend wrote in Go to Haskell so we can compare notes, and I think the Haskell is both safer and more elegant, but I'm jealous of the fact that all the libraries he used are from the standard library while I have to evaluate libs of varying quality. However, I would rather put my time in to improving the Haskell ecosystem than using something convenient that makes a lot of decisions I disagree with.
edit: I also think there's value in being a conventional imperative language as someone mentioned below. I with there were something between Go and Haskell. Perhaps that'd essentially be Rust with immutable data structures and garbage collection.
Clojure used to have something called, clojure contrib and it was kind of awsome, it did pretty much everything in just one jar. It was also a huge problem to mentain and everybody wanted to be in contrib, so you had the one json lib in contrib and fasters outside.
With clojure 1.3 it got split up into many diffrent parts and it still servs as somewhat of a community standard or recommended library. Overall its much better and much more usful, but sometimes I miss the days when everything was in one jar on on dependency.
As discussed elsewhere on this page, Go is not the most feature-rich language out there.
But it does have features that seem to help my solve my problems with a minimum amount of fuss. Like using interfaces liberally, instead of having to define classes. Having lexical closures is also nice.
If you're not working on an application that can benefit from concurrency, you may not see all the benefits of Go either.
What kind of problems were you trying to solve, and how did Go see heavyweight compared to how you'd solve the problem in some other language?
Most of what I've been working on is a Rest API. Here's an example of a problem that felt like it should be something for which I'd be able to write an abstraction to deal with, but turned out to be challenging, at least as a n00b:
https://groups.google.com/forum/#!topic/golang-nuts/JhsiiGHQ...
(Incidentally, though I moved past my then really poor understanding of Go interfaces, I wasn't able to apply the respondent's answer or my new general knowledge to achieve the abstraction I was looking for, and settled for just grinding out the same code for the dozen entities/endpoints it applied to.)
Concurrency: I suspect there's a bit that's hidden in some libraries we're using, and we may yet need to write our own code for some API requests that get processed offline, but I haven't had to explicitly write code for it yet.
If you can think of a specific exercise that might serve to illustrate Go's outstanding concurrency strengths, I'd be interested to try it and compare efforts to another language or two.
I definitely can't deny that using interfaces instead of regular OO classes takes some getting used to.
Though I don't understand why you had to grind out duplicate code for all the entities / endpoints though. I hacked up things a bit to get it to run on the playground, but as Jesse McNelis wrote, just passing the pointer to foo worked for the code you wrote.
I think implementing a simple HTTP proxy might also be a really good exercise, though I haven't done it.
If you have developed software in go, and after a couple months you aren't finding its saving you time, or at least pleasant to work with, maybe its not for you.
I feel like it is similar to C, but more opinionated, with much less rope to hang yourself, and often things I would have used C or Java, I find doing them in golang saves me plethoras of time.
It is opinionated, but for me the aha moment was after I learned enough of the standard libraries to feel comfortable in the language, I find myself getting things done at lightning speed, and it has performance that is as solid as the jvm in your average use case.
I find the code is also pleasant to read, and the language lends itself to writing verbose, simple code, which I find easier to debug than overly abstracted systems.
This, to me, is what he's missing. On the continuum between readable and expressive, Go falls decidedly on the readable side. If you're working on a project by yourself for 6 months, you might not like Go. But if you work on a team or return to code you wrote 6 months ago and haven't touched since, that's when you'll appreciate Go.
Evaluating languages based on simple solo projects will always favor the more expressive languages, but it's a short-sighted evaluation.
What makes Go my go-to language for certain kinds of projects (I'll doubtless be using it again) is that it gets shit done. It has the brutal simplicity and hardware proximity (and raw speed) of C combined with the small handful of things that most significantly contribute to make Java better than C: A simple type system, garbage collection, usable string handling and dynamic data structures (arrays and hash maps). Go also has a fairly large, useful library.
Multiple return values often including errors make error/exception handling very explicit and in-your-face. When something can go wrong, you the programmer are forced to recognize that and deal with it as soon as the function returns. That's a Good Thing IMO. Java-style exception handling, by comparison, looks to me like an elaborate language hack for passing the buck.
There's a ruthless kind of efficiency in Go's surrounding philosophy. There's one way to format Go code, you let the utility take care of it and never worry about formating again. The compiler won't tolerate various kinds of sloppiness, such as unused imports.
As somebody else mentioned, in Go, writing elegant code is not a consideration because it's nearly impossible. Well, I'm sure there are "better" and "worse" ways to write Go code, but not so obviously that I'd be tempted to give it a lot of thought. So I tend to just sit there and write code by the bucketful until I'm done.
Finally, the tooling gets the job done, and quickly. I can compile for and across various hardware environments and ship executables that don't rely on a JVM or other external dependencies.
I don't see why that would be true. In my experience, the most expressive languages often produce the most impenetrable spaghetti code. Can you explain your reasoning?
In a language with lenses, you can delimit where your models are mutated. In a language that lets you treat composable effects in a generic way, you can e.g. split up your variables explicitly with ReaderWriterState, making it clearer which serves which purpose.
The kind of things you might be tempted to use "magic" or global variables for in a lesser language - the "cross-cutting concerns" - you can instead handle in normal code as a generic kind of context. E.g. an audit trail can just be Writer. Or actions that need access to a database session can just be another kind of context. I'm working on such a thing right now (see tpolecat's doobie for a public example of the same kind of thing) - whether a function accesses the database or not is visible right in its type, but it's easy to compose functions that do. The types ripple up, and in the end I'm probably going to do session-creation-in-view - but in a principled way, using the ordinary type system, visible in the code - with Spray, my web route definitions are just another ordinary bit of Scala code (whereas in most languages I would define routes in an external config file, or at best a config object a la Django - adding complexity).
Heck, error handling is a perfectly good example of this. In a less expressive language, the only way around the boilerplate of handling errors where they occur is unchecked exceptions (or effectively-unchecked exceptions, as in "throws Exception"). In a language with good generic context support, the possibility of failure is just another kind of context that we compose with the same generic tools as any other, and the control flow becomes something sensible again.
more code has been written in Go than Haskell, Rust and Ocaml combined.
50 million? 100 million?
Powerful languages let you grapple with problems, weak languages first make you grapple with the language before tackling problems. Some people feel like Go gets in the way. I have not written any Go, but I understand both the praise and the criticism.
Powerful languages can cause other issues, but they do enable certain things that weaker languages simply never can.
[Citation needed]
Simple languages led to complex code bases.
Many of the Enterprise Java sins were caused by the language limitations and developers trying to work around them.
I have seen this happen in C codebases before Java took the enterprise.
Its own little macro based DSL and pointers that were actually handles for the real data.
Anyway Go has its use cases, and it is already an improvement if less C code gets written.
I'm repeating myself here, but: A Haskell user and a Lisp user are both sure that they're at the top of the power curve, and they're both sure that they're looking down when they're looking at the other language, and they can both tell you precisely why they're sure they're looking down ("It doesn't even have a decent type system" and "It doesn't even have macros", respectively). But they can't both be looking down. What's wrong here?
What's wrong is the assumption that all languages can be ranked by a one-dimensional attribute called "power".
Or look at it another way: Power? Power for what? Well, for writing programs. But what kind of programs? General programs? I've never written a general program in my life; I've only written specific ones. Then "power" is whatever's going to make it easier to write the program I need to write. Whatever language does that is the "most powerful" language for the problem I'm facing.
What power is Go shooting for? It's the power to write a ten-million-line application and have it be maintainable for two or three decades. (That's not my guess; it's what Rob Pike said the language goals are.) If you face that kind of problem, Go may in fact be a very powerful language.
I highly recommend to read this article where Rob lays out the motivation behind many aspects of Go: http://talks.golang.org/2012/splash.article
Maps, slices, the pre-defined functions.
More powerful languages make no big distinction between user defined types and the language provided ones.
But to your larger point, doesn't any non-programmable programming language exhibit the same weakness to some extent?
https://groups.google.com/forum/#!topic/golang-codereviews/A...
Then you have the option of using Java, Clojure, Scala, Ruby, Python, Javascript or Groovy languages.
which makes as much as sense as asking
- What about R? - What about GNU DAP? - What about FORTRAN?
for writing a TCP server.
Being good enough, not knowing any better PL-wise, and the Stockhold Syndrome explains that.
And I pretty much hate the language. I feel like I'm writing in something that combines the worst weaknesses of Pascal and Java. In fact, Mark Dominus' comments about Java (http://blog.plover.com/prog/Java.html ) approximate my experience Go far better than I would have guessed when I started the project I'm on.
People who seem to be smart nevertheless keep talking it up... some not even as just a good tool but as their favorite language.
So I'll ask: What is it I need to read/work through in order to at least "get" Go and really understand its strengths (whether or not I end up liking it)?