Some quarrels I have with go

blov · · 483 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>There are some quarrels I have with go.</p> <p>This is all find and dandy, there are quarrels I have with many language, happily enough there are over 1000 of them out there so I can simply leave behind the ones I dislike.</p> <p>However I like many things about go (speed, garbage collection, being able to execute system level operations in an almost sane and quick manner, nice community, good documentation for most stuff, easy-ish on the eye syntax, not a zealous focus on objects ... etc)</p> <p>Sadly enough, my quarrels with go give me quite a bit of trouble and I&#39;m not sure how easy they would be to fix. Maybe you guys have suggestions for how I should go about this.</p> <p>Errors:</p> <p>Basically go for dummies guides explains errors as &#34;You always have to deal with them by writing an explicit statement alike: if err ! = nil { //handle err }</p> <p>This is all fine and dandy until you get to calling ~5 different functions that all have a possible error as a return type, then it goes to shit and code gets 15 times bigger than it should.</p> <p>Isn&#39;t there a way to define an implicit error handling mechanism (similar to what C/C++ have, but using code explicitly written somewhere in the program)</p> <p>Sort of defining a &#34;for_error()&#34; function which gives a guideline for the program on how to act when an err is != nill. So I can just write</p> <p>whatever, err := my_func() or even better whatever := my_func() and get the error taken care of in a proper way, whilst still being able to define a custom error handling mechanism for things I deem as &#34;in need&#34; of custom error handling</p> <p>Package import:</p> <p>So, as to why exactly we need to be careful with the packages we import in a world that&#39;s heading for personal computer with a few Terabytes of RAM in ~5 years, I don&#39;t know.</p> <p>Maybe it makes the code easier to understand, maybe people writing good compilers have a reason for it, maybe they don&#39;t, but there are few of them skilled and influential enough to do it and we must accept various quirks they have, like believing that we still live in a world where memory is precious.</p> <p>However its quite very annoying to have to comment in/out &#34;fmt&#34; whenever I want to use some PrintX statement for debugging. Isn&#39;t there a sort of &#34;THIS IS NOT A PRODUCTION BUILD LEAVE MY PACKAGES ALONE&#34; flag I could specify before building and running ?</p> <p>Conversion:</p> <p>The fact that various functions return type64/32/16... etc and that I can&#39;t just say:</p> <p>var bar int = foo // where foo has type int64 Instead I must var bar int = int(foo)</p> <p>can be annoying when dealing with a lot of similar situations. Isn&#39;t there a way to specify that I&#39;d like my conversions to be implicit when the two values are very similar (e.g. ints and doubles) Also, is there something similar to Boost&#39;s lexical cast If I want to do conversions to a type without minding the type of the var being converted. E.g.</p> <p>s := strconv.magicoa(whatever) // where whatever can be of any type which can be reasonably converted to string, otherwise it throws and error, which is printed without 3 extra lines of code since I&#39;ve previously declared my magi error handling function</p> <p>Authoritarian format:</p> <p>I don&#39;t want to get into the whole why its good that we have the freedom to write code as we like, why its part of the creative process and why it make programming more enjoying. I&#39;ll just say that I like having ( ) around the arguments of my control statements and sometimes, especially when writing a large function, I feel like func foo() type { //contnet<br/> } is way nicer than foo() type{ //contnet }</p> <p>I&#39;d like to make go and gofmt to accept my own format, as long as it keep within reasonable standard (e.g. obivously due to missing &#34;;&#34; multiple statements on the same line would be kind of hard/impossible</p> <p>Am I completely glossing over a fix to any or all of these problems ?</p> <hr/>**评论:**<br/><br/>kardianos: <pre><p>use &#34;goimports&#34; to auto add-remove packages. Many project that don&#39;t do this struggle with unwanted dependencies that just add bloat. It is more a compile time issue and code quality issue. The Linker would always discard unused imports (unless inits have side effects).</p> <p>The largest benefit of gofmt isn&#39;t the formatting, it is all go code everywhere looks the same. Let go of your personal preference for the sake of state comrade.</p> <p>In Go, you handle errors.</p></pre>Carpetsmoker: <pre><p>This is the umpteeth rant about the same points that an umpteeth people have ranted about in the past.</p> <p>That is not to say that some aren&#39;t valid, just that it&#39;s all a repeat of things that have been said already, both here and in many other places.</p></pre>TheMerovius: <pre><p>I am unsure, what the point of your post is, TBH. There is nothing new here, these things have been complained about ad infinitum and have been replied to and discussed ad infinitum. So you are not going to change anyone&#39;s mind, really and the views of the go community on them are readily available elsewhere. As such, the point here seems mainly to vent and I don&#39;t think this is the best forum and audience to vent about your frustration with go. A personal blog or your friends seem to be a much better suited forum for that.</p> <blockquote> <p>Errors:</p> </blockquote> <p>This dead horse has been beaten to a pulp by now. Exceptions lead to hard to follow control flow, unreadable error messages emitted to the users and do not even really <em>have</em> the advantages touted by it&#39;s supporters, because now you need to litter your code with <code>try { … } catch { … }</code>, instead of <code>if err != nil</code>. It&#39;s also similar to Conversions (see below); error handling is hard and complicated and if you think the world would be better by hiding it away, you are not being rigorous enough with your error handling.</p> <blockquote> <p>So, as to why exactly we need to be careful with the packages we import in a world that&#39;s heading for personal computer with a few Terabytes of RAM in ~5 years, I don&#39;t know.</p> </blockquote> <p>Go was developed as a replacement for C++ at Google, where builds already have Terabytes of RAM and thousands of CPUs available today, so this is clearly a red herring. Tiny programs that you write on your home PC might compile quickly and not suffer from the difference, but even moderately sized programs will.</p> <p>Fast compile times are a key distinguishing factor of go (if you doubt that, just read this subreddit whenever a new version of go doesn&#39;t significantly bring them down, people are going <em>nuts</em> over it) and things like not importing stuff you don&#39;t use are a key strategy to get there. And as mentioned elsewhere, goimports can almost entirely eliminate the annoyance of it.</p> <blockquote> <p>Conversion</p> </blockquote> <p>Again, this is learned from experience. A conversion almost always has caveats and can lead to bugs, so doing it implicitly hides a <em>lot</em> of bugs (and a lot of them are security-related and can lead to DoS, e.g. because of failing bounds checks).If you believe that conversions can be done implicitly, you are not rigorous enough with your checks.</p> <blockquote> <p>Authoritarian format:</p> </blockquote> <p>It&#39;s not Authoritarian, it&#39;s opinionated (also, it&#39;s not required by the compiler, so at best you are complaining about the community here). And it&#39;s the favorite single feature of go for a lot of people. So you might not like it, but you are in a vanishingly small minority then and are unlikely to change anyone&#39;s mind.</p> <p>The things gofmt are opinionated on are exactly the things programmers in other languages spend <em>lifetimes</em> in lost productivity on debating about (case in point: Right now we are spending engineering hours debating about debating about them). <em>It doesn&#39;t matter</em>. If you really can&#39;t stand it, rewrite it to your favorite special snowflake style on checkout and gofmt on commit, done. But you could also just realize how it <em>really doesn&#39;t matter</em> and how much time and energy you save by not worrying about things that don&#39;t matter.</p> <p>After working with go for a while I pretty much refuse to work in languages without good auto formatting, because when I do, I immediately realize how much time I wast reformatting my code and how much energy I waste worrying if the linebreak should be before or after this HTML-element and how to best deal with inline-js. It&#39;s tiring.</p></pre>ngrilly: <pre><blockquote> <p>As such, the point here seems mainly to vent and I don&#39;t think this is the best forum and audience to vent about your frustration with go.</p> </blockquote> <p>I understand that reading the same questions over and over again can be frustrating, but this is not helpful.</p></pre>kune13: <pre><p>Let me give you the answers to your points:</p> <p><strong>Errors</strong></p> <p>Having explicit error handling is a great thing for larger projects. You still can choose to ignore them as exceptions usually are, but it doesn&#39;t feel good. From my point of view that is a good thing, handling errors is an important part of your program. If error handling feels repetitive, you can program around it. For instance by creating a wrapper type that saves errors and makes followup actions on the wrapper noops until the error is read and reset. </p> <p><strong>Package import</strong></p> <p>I recommend here to use goimports, which formats your code and handles the imports. There is even a workaround forcing the import.</p> <pre><code>var _ = fmt.Println </code></pre> <p><strong>Conversion</strong></p> <p>All what Go requires you is to make conversions explicit. That forces you to think about it and will prevent errors. BTW an int is not similar to a float64. For most integers they are similar, but not all 64-bit integers can be represented exactly by float64.</p> <p><strong>Authoritarian format</strong></p> <p>Every project involving more than one developer will have to agree on a single coding style. It is quite some work to develop and document one on your own. Go comes with a single coding style and a tool to support it. It&#39;s time saving. You can immediately read code somebody else has written and you don&#39;t need to care, because a tool is doing the formatting work.</p> <p>Your complains are pretty common for people coming to the language. But those features are there for a reason. Go&#39;s objective is to make it easy to produce production-ready, stable code in large projects. Lack of error handling, implicit conversions, unused dependencies and inconsistent coding styles don&#39;t support this objective and are therefore not supported or encouraged.</p></pre>luckyleprechaun98: <pre><p>The whole idea behind the error handling is to force you to deal with it in the context of where the error is retuned and to do it just once. Sometimes the right thing is to pass the error back to the caller, sometimes it will be to retry at the point of the error, or any number of variations. Having a generic error handling routine makes things more complicated because you&#39;re losing all the local context about what the right thing to do is in that particular situation. Are there more elegant ways of doing this in other languages? Of course, especially for function composition. But the one good thing about it is that it&#39;s explicit and easy to follow in Go when you haven&#39;t looked at a code base in a while. Try the same thing in Scala where you can have any number of fancy abstractions which cause you to hate your former self when you try to figure out what implicit magic you did and where the error is actually handled 6 months later. </p></pre>xiegeo: <pre><p>I find most of those features, when used correctly.</p> <p>Most of the authoritarian aspects are there to intentionally remove creativity. You will think it when working in a team, or coming back to an old project.</p> <p>For package import, there is a work around for packages that pop in and out:</p> <pre><code>import ( &#34;fmt&#34; ) var _ = fmt.Println </code></pre> <p>But it&#39;s still forcing you to make that exception, so you won&#39;t over use it. Go is a strict teacher, it&#39;s making you a better programmer.</p> <p>I think of it similar to dead code and unused assignment errors, slightly annoying during development, but good for code hygiene. And if I could turn them off during development, they are not turning themselves back on.</p></pre>FFiJJ: <pre><p>Oh, that is actually a reasonable fix... makes the code even larger &gt;&lt;, but at least it works. Thank you, I should have thought of that, now I feel silly :p</p></pre>btchsm: <pre><blockquote> <p>So, as to why exactly we need to be careful with the packages we import in a world that&#39;s heading for personal computer with a few Terabytes of RAM in ~5 years, I don&#39;t know.</p> <p>Maybe it makes the code easier to understand, maybe people writing good compilers have a reason for it, maybe they don&#39;t, but there are few of them skilled and influential enough to do it and we must accept various quirks they have, like believing that we still live in a world where memory is precious.</p> </blockquote> <p>What on earth are you talking about? forbidding unused packages has absolutely nothing at all to do with ram usage. I&#39;m not even sure how I&#39;d go about aligning stars such that that argument makes any sense...</p> <blockquote> <p>The fact that various functions return type64/32/16... etc and that I can&#39;t just say:</p> <p>var bar int = foo // where foo has type int64 Instead I must var bar int = int(foo)</p> </blockquote> <p>The implicit conversion is not done for a good reason. I&#39;d even go so far as to say implicit conversion here would be retarded.</p> <blockquote> <p>Am I completely glossing over a fix to any or all of these problems ?</p> </blockquote> <p>It sounds to me - especially with the way you talk about error handling - that you&#39;re trying to write PHP in Go. You should stop doing that.</p></pre>scottjbarr: <pre><p>Regarding RAM usage... Imagine that your app is running in a system that scales up and down depending on system usage. You might have 1,000 instances of your application running at any given time. Each instance will require a certain amount of RAM. That RAM costs you (or your employer) money. When doing things your way (&#34;I don&#39;t care how much RAM <em>my</em> app/server uses&#34;), actual $$$ is being wasted by paying for resources that could have easily been saved. RAM in &#34;the cloud&#34; is still relatively expensive.</p> <p>What about when your app runs on my machine? What about when every developer/team that produced software decided they didn&#39;t care how much RAM they used?</p> <p>Keeping RAM usage down matters. I&#39;m really pleased how the team behind Go has approached this, and after years of working with Ruby and Python I <em>really</em> appreciate how light on resources Go can be, without too much effort on behalf of the developer.</p> <p><em>(Edited. Fixed grammar/spelling)</em></p></pre>FFiJJ: <pre><p>If keeping RAM down matters so much then you can get into a whole other can of worms about how to best optimize each fucking loop and what un-heard to flags to use at compile time.</p> <p>I&#39;m not trying to compare GO with the ressource hogs that are scripting language like Python, Node, PHP, Perl... etc or ,god forgive, Ruby.</p> <p>But tbh I&#39;ve spoken with some amount of C and C++ programmers over my lifetime and I&#39;ve never once heard </p> <p>&#34;oh god, if only we wouldn&#39;t have forgot to remove that &lt;iostream&gt; include from that one class, man would that have saved us a lot of ressources&#34;</p> <p>Because, lets be honest, most useless packages that stay over are for debugging purposes and a warning would be enough</p></pre>scottjbarr: <pre><p>No need to reply in that tone.</p> <p>I&#39;m not talking about a can of worms. I&#39;m answering specifically about imports that aren&#39;t going to be used, which was the point your raised.</p> <p>Wire goimport up to the text editor or IDE of your choice, and move on with your life. The tooling is amazing.</p> <p>Also, it doesn&#39;t hurt to keep code tidy.</p> <p>These choices (e.g. errors from the compiler, not warnings) have been made for a reason, by a group of smart people that have been there and done that. Maybe we can learn from their experience.</p></pre>trentn81: <pre><p>Go.Back.To.Javascript. (now replace dots with whip cracks)</p> <p>Seriously, these are all addressed in the original Go design docs. They&#39;re a blessing and a curse, but they make the language for what it is. No need to be uniform to your other favourite languages</p></pre>

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

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