<p>Hi all. I've written a good deal of code in Python, C, C#, Java, and Rust, and I'm having kind of a hard time with Go. It might be that I've been spending too much time in Rust, but for a compiled language, it seems like Go's type system is insufficiently expressive, what with the lack of either generics or sum types.</p>
<p>What idioms are used to get around this? What is a good resource to learn about them? Many thanks.</p>
<hr/>**评论:**<br/><br/>ChristophBerger: <pre><p>"insufficiently expressive" for which purpose? Go is mainly a server backend/devops/tools language (although happily used for other purposes in many cases) with a focus on fast compilation and fast execution. The language spec has been deliberately kept small, first to achieve the speed and second to keep code readable. (Especially other people's code.) Hence if you want a feature-loaded language, Go is not for you. </p>
<p>About generics, they do not come free of cost, and the discussions about how to implement generics in Go have been summarized in <a href="https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/edit#">this document</a>. TL;DR: The Go team is not against generics but they have not yet found a way to integrate them into the language without compromising other important goals (like clear syntax and semantics, fast compilation, etc). </p>
<p>A while ago I wrote an article about a couple of alternatives to generics, as it appeared to me that people would demand generics even if the actual problem they tried to solve can be solved by other means. Find the article <a href="https://appliedgo.net/generics">here</a>. Caveat: The article heading may sound like "Go needs no generics", but this is far from what I actually want to say in this article. The point is, there are some useful techniques in Go that make the need for generics less urgent.</p>
<p>Bottom line: If you work in an area where generics, sum types, and similar constructs are intensely used, you probably do not want to use Go there.
If you just want to learn Go to have it "on your toolbelt" (which is what the title seems to imply), then by all means do it, and feel welcome in the Go community... but just don't mention the g-word again
- at least not in this subreddit ;-)))</p>
<hr/>
<p>EDIT: More articles on generics and sum types:</p>
<p><a href="http://bouk.co/blog/idiomatic-generics-in-go/">http://bouk.co/blog/idiomatic-generics-in-go/</a></p>
<p><a href="http://blog.jonathanoliver.com/golang-has-generics/">http://blog.jonathanoliver.com/golang-has-generics/</a></p>
<p><a href="http://www.jerf.org/iri/post/2917">http://www.jerf.org/iri/post/2917</a></p>
<p><a href="https://medium.com/@haya14busa/sum-union-variant-type-in-go-and-static-check-tool-of-switch-case-handling-3bfc61618b1e">https://medium.com/@haya14busa/sum-union-variant-type-in-go-and-static-check-tool-of-switch-case-handling-3bfc61618b1e</a></p>
<hr/>
<p>EDIT: Also VERY interesting is this approach on polymorphism in Go (actually, it is a language extension on top of Go and transpiling to Go):</p>
<p><a href="https://github.com/lukechampine/ply">https://github.com/lukechampine/ply</a></p>
<hr/>
<p>EDIT: typo.</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>keep code readable</p>
</blockquote>
<p>I think this is the main thing I have an issue with; expressive, comprehensively checked types make code more readable for me. However, given that three people, one of whom invented a popular programming language, have now told me that some people don't feel that way, I recognize that my preference is probably just that - a personal, aesthetic preference. So, fine.</p>
<blockquote>
<p>fast compilation</p>
</blockquote>
<p>Given the number of coffees I've drunk while waiting for Rust code to compile, I definitely feel this pain and understand why this is a big deal for the language maintainers.</p>
<blockquote>
<p>If you just want to learn Go to have it "on your toolbelt" (which is what the title seems to imply),</p>
</blockquote>
<p>Whoops! I didn't mean to imply that. I'm learning Go for a job, and I really do want to understand how the Go community does things. This answer has been quite valuable for that, so thank you.</p>
<p>Thank you also for those links; they seem very useful, and I'll definitely spend time going through them.</p></pre>ChristophBerger: <pre><blockquote>
<p>expressive, comprehensively checked types make code more readable for me.</p>
</blockquote>
<p>Agreed. My point on readability is more about the number of features a language has. In feature-rich languages, programmers are exposed to the danger of over-engineering their code. They start focusing on creating "clever" constructs using all those cool features in order to solve a problem in an "elegant" way, perhaps just to prove they have "understood" the language at black belt level, and the resulting code is just incomprehensible to anyone else.</p>
<p>I frequently hear people saying that reading Go code of other people is a delight compared to other languages. </p>
<p>(Yes, this readability is partly also due to <code>gofmt</code>.)</p>
<blockquote>
<p>If you just want to learn Go to have it "on your toolbelt" (which is what the title seems to imply),
Whoops! I didn't mean to imply that. </p>
</blockquote>
<p>Misunderstanding on my end, sorry for that!</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>I frequently hear people saying that reading Go code of other people is a delight compared to other languages.</p>
</blockquote>
<p>Well that's good! I have yet to read much Go code outside of tutorials and examples, but since I'm about to be thrown into a huge codebase about two weeks from now I hope this holds true :)</p></pre>ChristophBerger: <pre><p>Well, good luck and fingers crossed! :)</p></pre>brokedown: <pre><p>Look at the go standard library. It's all go, and generally great examples of how good go should be written.</p></pre>jerf: <pre><p>I also wrote <a href="http://www.jerf.org/iri/post/2945" rel="nofollow">Avoiding Reflection (And Such) In Go</a>, which has some relevant tips.</p>
<p>Let me echo <a href="/u/ChristophBerger" rel="nofollow">/u/ChristophBerger</a>'s point that I don't believe this means they "generics are useless", nor that I've never quite encountered a case where I'd like them. I've a pretty fair hand with Haskell; I get that sort of thing. But when trained on generics it's easy to forget or not realize when they aren't actually <em>necessary</em>.</p>
<p>And I also advise that there are certain types of programs for which generics are really, really useful to the very core functionality, and I advise against using Go in those cases.</p></pre>ChristophBerger: <pre><blockquote>
<p>But when trained on generics it's easy to forget or not realize when they aren't actually necessary.</p>
</blockquote>
<p>A very important and often underestimated factor. It's like getting rid of good old habits. Very difficult.</p></pre>PsyWolf: <pre><p>You need to learn the power of interfaces.</p>
<p><a href="http://stackoverflow.com/a/21567136/2012396" rel="nofollow">Nemo's answer to this SO question</a> shows how to use them to make type safe sum types with interfaces.</p>
<p>Interfaces can also allow for generic programming in some cases. <a href="https://golang.org/pkg/sort/#example_Slice" rel="nofollow">The stdlib sort function</a> is a great example of this.</p>
<p>The one generic thing you really can't do with interfaces is functional programming. Do not try to bring your map, reduce, filter, flatten, etc paradigms into go. The "correct" way to transform a list in go is a for loop. This makes some people sad, but it's really a small syntactic difference that most polyglots get used to after a little grumbling. </p>
<p>Edit: I almost forgot, in the very rare cases where interfaces do not suffice and you absolutely need generics for something, there are plenty of tools like <a href="https://github.com/clipperhouse/gen" rel="nofollow">https://github.com/clipperhouse/gen</a> that will essentially do the same preprocessing that C++ templates do in the form of code generation. I want to stress again that this is a measure of last resort. 99% of the time, interfaces can do what you need. </p>
<p>Edit 2: the most thorough way to learn these concepts (diving off the deep end) would be to write something that reads the ast of go files using <a href="https://golang.org/pkg/go/ast/" rel="nofollow">the go/ast package</a>. It's not pretty, but it works, and if you can represent and work with an AST without sum types or generics, you can do anything. </p></pre>SilverWingedSeraph: <pre><blockquote>
<p>The one generic you really can't do with interfaces is functional programming.</p>
</blockquote>
<p>That's really good to know. Thank you.</p></pre>PsyWolf: <pre><p>To be clear, go has closures and functions are first class citizens which is all you technically need to do functional programming, but without generics, general higher order functions lose type safety. Rob Pike wrote <a href="https://github.com/robpike/filter" rel="nofollow">this package</a> to show that in go, these paradigms are A) technically possible but B) ugly as sin.</p>
<p>Russ Cox is taking <a href="https://research.swtch.com/go2017#generics" rel="nofollow">another look</a> into the generics design space this year. The last time they looked, <a href="https://research.swtch.com/generic" rel="nofollow">this was the state of the world</a>.</p></pre>SilverWingedSeraph: <pre><p>Well, I'm glad to know that there has been a lot of thought behind these decisions, and I'll definitely spend some time looking at those links. Thank you!</p></pre>weberc2: <pre><p>I don't think generics are a big deal; I can probably count on one hand the times I've needed them. The conventional workaround is to use the <code>interface{}</code> type and accept the slight hit to type safety and performance; if those compromises aren't acceptable, use code generation.</p>
<p>On the other hand, sum types are generally useful. If you want to do similar things with each permutation, define those things as methods on an interface, and then make each type implement that interface. If you want to do different things with each type, you can still use an interface with a single private "iAmAFooInterface()" method that everything implements (this is mostly just a type safety hack) and then do a type switch instead of pattern matching. This isn't exactly the same as sum types, and it certainly requires a lot of boilerplate.</p>
<p>Personally, I prefer creating a 'Type' enum (in the C sense of the word) with one value per sum-type permutation and then creating a struct with one field per permutation as well as a 'Type' field whose type is the aforementioned enum type; when you need to use this type, just switch on the 'Type' field. Mostly I like this approach because I find it to be more clear than the interface approach, but I think it has other benefits. It still requires a bit of boilerplate, but less than the interface method. Also, it wastes a few words of memory per instance, but this is usually a better compromise because it can all live in the stack instead of an alloc per instance (interfaces typically require an alloc, though I think there are exceptions if the concrete type is already a pointer or perhaps an int)--in other words, if you have a slice of these things, it's one alloc, but if you have a slice of interfaces, it's N+1 allocs.</p>
<p>Now, some Go apologetics: These pain points are common. Go is less ideologically pure than Rust, but you'll quickly realize that Go's impurities are probably not that big of a deal overall (it's arguably better to sacrifice purity than complicate an otherwise simple language). For example, people often balk when they realize that the common workaround for generics is not type safe, but then again, these code paths are < 1% of all code (and often trivial from a typing perspective), and entire projects are built with Python, Ruby, and JS which are 100% type-unsafe. I can certainly appreciate the argument that the complexity cost introduced by generics might outweigh the type-safety/ergonomic cost from their omission.</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>entire projects are built with Python, Ruby, and JS which are 100% type-unsafe</p>
</blockquote>
<p>Sadly, yes :P But I take your meaning. I need to get over my purity obsession.</p></pre>weberc2: <pre><p>I'm the same way. I find that I often have to choose between elegance and completion. I find that with Go I'm much more likely to complete a project and it won't be <em>too</em> inelegant. :)</p></pre>nstratos: <pre><p>Welcome to Go!</p>
<blockquote>
<p>it seems like Go's type system is insufficiently expressive</p>
</blockquote>
<p>One of the Go creators explains why Go is the way it is in <a href="https://www.youtube.com/watch?v=rFejpH_tAHM" rel="nofollow">this talk</a>. </p></pre>SilverWingedSeraph: <pre><p>Hmm. I don't know that I completely agree with him there. He argues that more features make programs more confusing and less readable because there are so many ways to do things, but I don't really think that's a valid complaint. There are always lots of ways to do things; some of them are right.</p>
<p>For instance, in Rust, there are a lot of ways to do things, but only one of them is <em>right</em>; that is, the most restrictively typed, most restrictively borrowed, least copying way. Errors, for example, are often done using strings in prototypes:</p>
<p><code>fn do_something(x: i32) -> Result<i32, String></code></p>
<p>This is very similar to error handling in Go, but <em>even in this lax case</em> the type system ensures at compile time that the caller handles that error. In addition, most production-ready systems use sum types for errors, e.g.</p>
<pre><code>enum DoSomethingError {
FailedWrite(String),
FailedRead(String),
FailedSpellcast(String),
// etc
}
fn do_something(x: i32) -> Result<i32, DoSomethingError>
</code></pre>
<p>This not only ensures that the caller handles the error, but if that caller doesn't chose to panic on error (with <code>.unwrap()</code> or <code>.expect()</code>), it ensures that they handle <em>every possible error</em>.</p>
<p>In Go, however, this is not an option at all. Not only can Go not have a Result type (because it doesn't have generics), you can't even use sum types to statically ensure that all cases are checked.</p>
<p>This isn't necessarily a bad thing; I just don't understand the motivation behind it, or what idioms are used to get around it.</p></pre>bkeroack: <pre><p>"Programming is made up of 2 activities: making decisions (95%), and typing (5%)"</p>
<p>"corollary: optimize code for easier decisionmaking (broadly: for reading) rather than for easier typing (writing)"</p>
<p><a href="https://twitter.com/peterbourgon/status/853596055971274752" rel="nofollow">https://twitter.com/peterbourgon/status/853596055971274752</a></p></pre>SilverWingedSeraph: <pre><p>I absolutely agree with that quote, and in my opinion, having a more expressive type system does that; am I missing something?</p></pre>bkeroack: <pre><p>I disagree. The more ways there are to do something the harder it is to decide ultimately how to do it. I think we've all had the experience (if we're being honest) of spending an hour fiddling with a piece of code to reduce it by a few lines, or to make it more "beautiful".</p>
<p>With Go, there's usually only one way to do something idiomatically. You can just do it move on to the next thing.</p>
<p>This also yields rewards later on when you go back to read your code. I don't know how many times my "beautiful" code in other languages turned out to be inscrutable a few months later. Hence my reference to "optimize code for easier [reading]". I think that sentence could be used as an unofficial slogan for Go.</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>With Go, there's usually only one way to do something idiomatically.</p>
</blockquote>
<p>"idiomatically" is the important word here. I think this is true in most modern languages, including Rust, Python, and even Java.</p></pre>weberc2: <pre><p>A more expressive type system (probably by definition) increases the decision space by increasing the permutations for expressing the same program. I recently heard a clever quip about how Haskell can be confusing simply because there are soooo many ways to do the same thing, and for this reason every programmer's approach to a particular problem looks different.</p>
<p>For example, I don't need to choose between higher-order functions and generators, because Go only supports one. This also means everyone's code looks the same.</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>I don't need to choose between higher-order functions and generators, because Go only supports one</p>
</blockquote>
<p>Right - but what happens when you need the other one?</p></pre>weberc2: <pre><p>The use cases for higher order functions are a strict subset of the use cases for <code>for</code>.</p></pre>SilverWingedSeraph: <pre><p>I would absolutely love to see a proof of that, if one exists. (Note: I'm not saying I don't believe you. It would just be cool to see a proof.)</p>
<p>This is like saying that the use cases <code>for</code> are a strict subset of the use cases for <code>GOTO</code>, or of <code>jle</code>. Of course they are, but I still want <code>for</code>.</p></pre>weberc2: <pre><blockquote>
<p>I would absolutely love to see a proof of that, if one exists. (Note: I'm not saying I don't believe you. It would just be cool to see a proof.)</p>
</blockquote>
<p>I don't know about a formal proof, but I know I can rewrite any <code>map</code> program with <code>for</code> because I can build <code>map</code> with <code>for</code> (therefore, by substitution, I can rewrite any <code>map</code> program with <code>for</code>). I also know that there are things I can do with <code>for</code> that I cannot do with <code>map</code>--for example, modifying an array in place.</p>
<p>For any sane definition of "higher order function", I can take each function in the set of HOFs and substitute it for <code>map</code> in the above paragraph, and all statements therein remain true.</p>
<blockquote>
<p>This is like saying that the use cases for are a strict subset of the use cases for GOTO, or of jle. Of course they are, but I still want for.</p>
</blockquote>
<p>You can't implement <code>for</code> with just <code>GOTO</code>, you also need a conditional mechanism. I don't know what <code>jle</code> is. We prefer <code>for</code> to <code>GOTO</code> because the latter is more powerful (principle of least power), which is the same reason why some prefer HOFs to <code>for</code>; however, there are other principles at place. For example, a single versatile function is often better than all of its factorized derivatives--add(a, b) is nicer than {add1(b), add2(b), add3(b), ... }).</p></pre>EZYCYKA: <pre><blockquote>
<p>I don't know what jle is.</p>
</blockquote>
<p>Just a guess, but "jump if less or equal"?</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>I don't know what jle is.</p>
</blockquote>
<p><code>jle</code> is the mnemonic for <code>7E</code> and <code>0F 8E</code> opcodes on x86. It stand for <strong>J</strong>ump if <strong>L</strong>ess than flag is set or <strong>E</strong>qual flag is set.</p>
<blockquote>
<p>We prefer for to GOTO because the latter is more powerful (principle of least power), which is the same reason why some prefer HOFs to for;</p>
</blockquote>
<p>This is true, but we also prefer <code>for</code> to <code>GOTO</code> (or, as you accurately point out, <code>GOTO</code> plus <code>if</code>) because it is more expressive. This is the same reason we prefer <code>for value := range ch</code> to a simple infinite loop with if statements and <code>break</code>. The same holds true for HOFs.</p></pre>TheMerovius: <pre><blockquote>
<p>I just don't understand the motivation behind it, or what idioms are used to get around it.</p>
</blockquote>
<p>Well, the motivation is given in the talk you just watched :)
When I see code in languages with a more powerful type system (be it Java, C++, Haskell or, yes, Rust), there seems to be a lot of focus on developing a type hierarchy and signatures that make it impossible to use the thing wrong. As a consequence, there will be friction when reading the code (as there are additional layers of abstraction), when maintaining the code (code that is harder to use wrong is also harder to use creatively or to change) and also when writing in the language in the first place (you first need to think very hard not only how you want your thing to be used and why it is correct; but also how you can convince the compiler that it is, indeed, correct. I don't like arguing with compilers too much, I rather want them in the role of providing helpful advice).</p>
<p>In general, go goes the middle-ground; have a strict enough type-system to catch most common errors and feel somewhat safe when refactoring, while also making it hard to build abstract code and in general trust the programmer to do the right thing.</p>
<p>For example, while you can do getters and setters in go and enforce safety in them (e.g. "you can't change the logger concurrently with serving requests"), it's in general deemed unnecessary and totally fine to just export that member and tell people to not do dumb things (see, e.g. <a href="https://godoc.org/net/http#Client" rel="nofollow">http.Client</a> -- you could totally concurrently modify the client while it's also used to do requests. But that'd be stupid, set it up first, then use it, simple as that).</p>
<p>These things always seem like a bad idea to people who are used to "keep things as private as possible" and similar mantras from the OOO world. But for whatever reason, empirically they seem to work. Go code is generally observed to be pretty safe, have a low frequency of bugs and to be relatively easy to debug (which, arguably, is the reason that the debugger-story for go isn't as fleshed out as for other languages). In my opinion it's because the simple design forcing you to write simple code pays off; YMMV.</p></pre>SilverWingedSeraph: <pre><blockquote>
<p>code that is harder to use wrong is also harder to use creatively or to change</p>
</blockquote>
<p>That absolutely makes sense, and sort of changes my perspective on the issue.</p>
<blockquote>
<p>I don't like arguing with compilers too much, I rather want them in the role of providing helpful advice</p>
</blockquote>
<p>Again, I think this is something I thought was an absolute which turns out to be something of an aesthetic choice. I personally love it when my compiler tells me that I have written a program that's in some way internally inconsistent, but apparently that's not universal.</p>
<blockquote>
<p>simple design forcing you to write simple code pays off</p>
</blockquote>
<p>Seems like a good philosophy, and, as you say, it's empirically effective. </p>
<p>Thank you!</p></pre>dinkumator: <pre><p>The "confusing and less readable" part is when seen from a novice's perspective. Go is really designed to make it hard to do things wrong, especially when you have a lot of junior developers on a project that maybe don't have the experience or breadth necessary to follow e.g. your examples here.</p>
<p>For a few senior devs on a complex project, there is certainly some weight to using more powerful expressions. But if your project will be picked up by a team of 100, you need to ensure that the less experienced folks can still contribute without issue.</p></pre>SilverWingedSeraph: <pre><p>That makes sense. Thank you!</p></pre>snippet2: <pre><p>Is a good source to learn.
<a href="https://www.ossblog.org/assimilate-go-programming-open-source-books/" rel="nofollow">https://www.ossblog.org/assimilate-go-programming-open-source-books/</a></p>
<p>Basically you want to know about :</p>
<p>open interface {} (can take in any data type)
Useful for type switches <a href="https://newfivefour.com/golang-interface-type-assertions-switch.html" rel="nofollow">https://newfivefour.com/golang-interface-type-assertions-switch.html</a></p>
<p>Creating data types
Adding these data types to a struct (especially function types}</p>
<p>Knowing how to use slices [1:][:1] (gets rid of a ton of need for array methods)
<a href="https://tour.golang.org/moretypes/7" rel="nofollow">https://tour.golang.org/moretypes/7</a></p>
<p>Here is a good Dave Chaney video about first class functions and pointers
<a href="https://youtu.be/5buaPyJ0XeQ" rel="nofollow">https://youtu.be/5buaPyJ0XeQ</a></p>
<p>And many great os methods!</p>
<p>If you are a visual learner
A good udemy course <a href="https://www.udemy.com/mastering-go-programming/learn/v4/" rel="nofollow">https://www.udemy.com/mastering-go-programming/learn/v4/</a></p></pre>SilverWingedSeraph: <pre><p>Thank you! Many of these concepts are very useful, and most are available in other languages that I've already learned. Goroutines make a lot of sense to me and I'm very excited to use them.</p>
<p>interface {} is somewhat confusing to me, however. It seems as if Go handles the type system's lack of expressiveness by becoming dynamically typed sometimes. Is that the case?</p></pre>tylermumford: <pre><p>I'm not an expert, but this line of the documentation helps me understand: <a href="https://golang.org/ref/spec#Interface_types" rel="nofollow">link</a></p>
<blockquote>
<p>A variable of interface type can store a value of any type with a method set that is any superset of the interface.</p>
</blockquote>
<p>In other words, interface types don't give you any guarantees about the actual underlying type of data you're working with; they only guarantee that the actual underlying type implements that interface. I don't think this counts as dynamic typing, but again, I'm a relatively new programmer.</p></pre>SilverWingedSeraph: <pre><p>I'd call that static duck typing, and that makes a lot more sense than what I thought was going on. Thank you!</p></pre>jerf: <pre><p>The "dynamic typing" aspect of Go is in the "reflect" module, which basically gives you the machinery of a C-level dynamic language interpreter and allows you to write dynamic code as if you were writing a plugin for Python in C. It's tedious and only as fast as an interpreted dynamic language is, because that's basically what it <em>is</em>, but it is available for selected locations where that makes sense. Go certainly does not encourage heavy use of that, but because everything in Go is actually tagged with its type you can dabble in it.</p></pre>Uncaffeinated: <pre><p>interface{} is pure dynamic typing. Interfaces with methods are a bit more of a grey area.</p></pre>snippet2: <pre><p>Don't get too caught up in genetics <a href="https://m.youtube.com/watch?feature=youtu.be&v=rFejpH_tAHM&t=1m" rel="nofollow">https://m.youtube.com/watch?feature=youtu.be&v=rFejpH_tAHM&t=1m</a> </p>
<p>Open interfaces and data types are wonderful!
Almost all things in golang can have multiple data types and you can use them to cycle through structs.
<a href="https://play.golang.org/p/9FULo4AcNr" rel="nofollow">https://play.golang.org/p/9FULo4AcNr</a></p>
<p>If you want verification.
This is kinda like var_dump but better
<a href="https://godoc.org/github.com/davecgh/go-spew/spew" rel="nofollow">https://godoc.org/github.com/davecgh/go-spew/spew</a> </p>
<p>A debugger
<a href="https://www.google.com/amp/blog.cloudflare.com/go-has-a-debugger-and-its-awesome/amp/" rel="nofollow">https://www.google.com/amp/blog.cloudflare.com/go-has-a-debugger-and-its-awesome/amp/</a></p>
<p>And use gogland
<a href="https://www.jetbrains.com/go/" rel="nofollow">https://www.jetbrains.com/go/</a></p>
<p>Also, use jump to declaration in gogland because go is written in go so you can definitely know what you are working with instead of guessing. </p>
<p>A great project to start learning and get familiar with structure is using bufio core package to read your code files and print the vars, structs, and functions in your go files in the terminal. It's easier to digest and gets you familiar with go code. </p>
<p>Here is a video on counting text in a file
<a href="https://youtu.be/ptbe-2aBFJI" rel="nofollow">https://youtu.be/ptbe-2aBFJI</a></p></pre>SupersonicSpitfire: <pre><p>Why gogland over LiteIDE, though?</p></pre>snippet2: <pre><p>Sorry, just got off for lunch. It's bigger but just ease of use (great debugging, great intellisense, great database management, and youd be surprised how fast they respond) and no setup. But yeah eventually gotta pay. </p>
<p>As far as doing extra things in C. Sure you can do extra things in C but not only are their steps but every time you pick up the code you mentally have to think about what you were thinking about when you wrote it and unless you are a lifetimer there, forget about others reading your code. The point of making readability first is to design a language where people's minds are important. This is important in any understanding of science. </p></pre>SupersonicSpitfire: <pre><p>Not sure about the C part, but LiteIDE has integrated debugging and features like "jump to definition". It's also fully open source.</p>
<p>Heading for bed.</p></pre>Perfekt_Nerd: <pre><p>Late to the party here, but to quote Russ Cox on this:</p>
<blockquote>
<p>Go is more an engineering project than a pure research project. Like most engineering, it is fundamentally conservative, using ideas that are proven and well understood and will work well together. The research literature’s influence comes mainly through experience with its application in earlier languages. For example, the experience with CSP applied in a handful of earlier languages—Promela, Squeak, Newsqueak, Alef, Limbo, even Concurrent ML—was just as crucial as Hoare’s original paper to bringing that idea to practice in Go. Programming language researchers are sometimes disappointed that Go hasn’t picked up more of the recent ideas from the literature, but those ideas simply haven’t had time to pass through the filter of practical experience.</p>
</blockquote></pre>Uncaffeinated: <pre><p>Go is a strongly opinionated language that emphasizes simplicity of the language at the expense of nearly everything else, including safety, performance, code reuse, and readability. If that doesn't sound appealing, Go is not the language for you.</p></pre>mmrath: <pre><p>I am Java developer, just recently started looking at go. With go i fells less powerful, the type system is too weak with interfaces{} all around. But there are some good thing like gofmt, compilation speed, convention of Pascal case to be public. It is lacking some good libraries for web development. So at the moment I think it is still a very good choice for some work but if you are looking at web backend development there are too many better choice. I am also looking at Rust, which feels like a much better language for its domain.</p></pre>snippet2: <pre><p><a href="https://dave.cheney.net/2015/07/02/why-go-and-rust-are-not-competitors" rel="nofollow">https://dave.cheney.net/2015/07/02/why-go-and-rust-are-not-competitors</a></p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传