TBH... Why someone should need generics? A question.

blov · · 485 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I have a solid C background and i&#39;m enjoying a lot Go and its composition. I never felt the need for generics, and sometimes (totally IMHO) i think that they are limited to such few cases that i can call &#34;lazy programmers&#34;. Can you tell me how big this deal is?</p> <hr/>**评论:**<br/><br/>joncalhoun: <pre><p>This question literally gets asked weekly, and every time you see someone post a use case and then someone else respond to them saying it isn&#39;t a true use case. It usually turns into somewhat of a flame war.</p> <p>Everyone has different opinions of the need, but the most common use case pointed to would be data structures. Lists, Sets, Trees, Stacks, Heaps, etc.</p></pre>8lall0: <pre><p>I&#39;m lurking this reddit for like a couple of weeks, i didn&#39;t know about the &#34;weekly&#34; asking, sorry :)</p></pre>joncalhoun: <pre><p>No worries! I realize now that my response may have come across harsher than intended, so sorry for that.</p> <p>Unfortunately these discussions never seem to end amazingly well. Either people agree with the use case for generics and support it strongly, or they don&#39;t and disagree strongly. </p> <p>There are likely some in the middle as well but those usually aren&#39;t the ones commenting, so you end up with two sides who disagree with one another speaking &#34;passionately&#34; about what they think is the right decision. It can grow slightly tiresome after a while since nothing productive tends to come from it.</p></pre>dlsniper: <pre><p>Make sure you use the search functionality before asking. Chances are someone else had the question before you.</p></pre>earthboundkid: <pre><p>I agree that people want different container types, but Doubly Linked List is a bad example because Go&#39;s slice will outperform it in almost any scenario. Deques however are useful and would be nice to have. </p></pre>joncalhoun: <pre><p>Look up a linked hash map. It is a combination of a linked list and a hash map used to implement a fast LRU (least recently used cache).</p> <p>This is just one case where linked lists outperform slices, because deletes can happen in constant time vs O(N)</p></pre>earthboundkid: <pre><p>Yes, but that&#39;s not a linked list; it just has a linked list as part of its implementation. ;-)</p> <p>I&#39;m mostly just complaining about linked list because it is the bubble sort of data structures: it is well known because it is pedagogically useful, but there are very few cases where it by itself is a good choice absent some unusual mitigating factors.</p></pre>joncalhoun: <pre><p>It is a linked list though. It is a linked list + a hash map to elements in the linked list, so if we had generics and linked lists we could use the built in map to make an LRU cache.</p></pre>__CAFxX: <pre><p>Think C without macros. You can definitely live without them but sometimes they are really handy. They have some downsides (add complexity, especially if abused, and are hard to debug) and upsides (can reduce repetition and mistakes).</p></pre>rjc2013: <pre><p>Another downside: build times. Looking at you, C++...</p></pre>Tyler11223344: <pre><p>I assume you&#39;re referring to templates, not macros?</p></pre>rjc2013: <pre><p>Yes, templates.</p></pre>itsmontoya: <pre><p>Writing any data store (such as: Hashmap, BTree, RBTree, Skiplist, etc) is quite bothersome without generics. You end up relying on interface{} to handle your values which presents a couple problems:</p> <ul> <li>Performance: Overhead of using interface{} instead of direct type</li> <li>Messy code: Utilizing type assertion adds unnecessary complexity to the codebase</li> <li>Unsafe: Utilizing type assertion forces our type checks to occur at runtime instead of at compilation time</li> </ul> <p>While I do agree that generics aren&#39;t necessary for 99% of golang libraries. If you are writing a low-level library, you will find yourself encountering a need for generics more often than not. </p></pre>10F1: <pre><ul> <li><p>The convenience of type safety and knowing the type before hand rather than at runtime using <code>v, ok := x.(SomeType)</code> for an <code>interface{}</code>.</p></li> <li><p>Performance, using interfaces{} have a noticeable overhead (although it&#39;s getting pretty tiny in recent Go releases)</p></li> </ul> <p>Here&#39;s a very simple example from my own project, <a href="https://github.com/OneOfOne/cmap" rel="nofollow">cmap</a>:</p> <p>the <code>map[interface{}]interface{}</code> based version is 2.5x slower than the <code>map[string]interface{}</code> version.</p> <pre><code>CMap/4096-8 86.5ns ± 1% # vs StringCMap/4096-8 37.9ns ± 5% </code></pre></pre>gott_modus: <pre><blockquote> <ul> <li><p>The convenience of type safety and knowing the type before hand rather than at runtime using <code>v, ok := x.(SomeType)</code> for an <code>interface{}</code>.</p></li> <li><p>Performance, using interfaces{} have a noticeable overhead (although it&#39;s getting pretty tiny in recent Go releases)</p></li> </ul> <p>Here&#39;s a very simple example from my own project, <a href="https://github.com/OneOfOne/cmap" rel="nofollow">cmap</a>:</p> <p>the <code>map[interface{}]interface{}</code> based version is 2.5x slower than the <code>map[string]interface{}</code> version.</p> <p>CMap/4096-8 86.5ns ± 1% # vs StringCMap/4096-8 37.9ns ± 5%</p> </blockquote> <p>That&#39;s hardly insignificant: it&#39;s almost 3x as slow.</p></pre>epiris: <pre><p>Performance cost of type assertions for interfaces is around a nanosecond. The penalty of them only really shows when you cause allocations in places that would otherwise satisfy escape analysis. The map examples probably show 0 allocations for stringcmap because string doesn&#39;t have to allocate, while interface does.</p></pre>GentooMonk: <pre><p>That&#39;s exactly the point, if you&#39;re not using a pointer they will have allocations.</p> <p>Also all extra <code>v.(sometype).XXX</code> gets pretty ugly, or you have to check the value.</p></pre>epiris: <pre><p>I didn&#39;t miss the point, I just feel it&#39;s the last reason to avoid interfaces because there are plenty of others that I find more costly.</p></pre>10F1: <pre><p>I literally released <a href="https://github.com/OneOfOne/genx" rel="nofollow">https://github.com/OneOfOne/genx</a> today just to counter that issue.</p></pre>gott_modus: <pre><p>Cool, maybe I&#39;ll look at it later. I&#39;m getting drunk right now though, chatting with boys and gals on facebook, and am about to watch The Departed.</p></pre>Justinsaccount: <pre><p>The C solution for generics is functions that work with <code>void *</code> pointers. An empty interface in go is basically the same thing. If you&#39;re comfortable dealing with void pointers in C, you probably don&#39;t see anything missing in go.</p></pre>TheMerovius: <pre><blockquote> <p>An empty interface in go is basically the same thing.</p> </blockquote> <p>This statement was never true and never will be true. <code>interface{}</code> is type-safe (even though not statically type-checked), whereas <code>void*</code> is not. Yes, the difference is important.</p></pre>8lall0: <pre><p>I agree with both of you. I only found that if you&#39;re using too much void* (or similar constructs), you&#39;re dealing with a bad design issue.</p></pre>hein_bloed: <pre><p>Same with strong type system, functions, classes, oop, garbage collection and literaly everything except asm. Some like it, some dont need it.</p></pre>recurrency: <pre><p>this overview on the subject from the golang wiki</p> <p><a href="https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/edit?pli=1#" rel="nofollow">https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/edit?pli=1#</a></p></pre>stone_henge: <pre><blockquote> <p>i think that they are limited to such few cases that i can call &#34;lazy programmers&#34;.</p> </blockquote> <p>That&#39;s the gist of it, but saving time and energy is a virtuous pursuit.</p></pre>newtyped: <pre><p>Interesting you use the phrase &#34;lazy programmer&#34;. I actually consider that a very important part of developing code (see <a href="http://blogoscoped.com/archive/2005-08-24-n14.html" rel="nofollow">Why Good Programmers Are Lazy and Dumb</a>). This is just a balance of what you think is enough for your use cases. Some languages (like Idris or Coq) have (dependent) type systems that even let you have compile time checks that your indices are not out of bounds. </p> <p>Personally, I find that reasoning about the types of things (including generics) lets me have a deeper understanding of what is going on. All the way at the end of that spectrum are dependent types, where you sometimes have to prove to the compiler some property or invariant holds in your code.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

485 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传