What is idiomatic Go?

blov · · 448 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I checked <a href="/r/golang">/r/golang</a> this morning to see what is up to find <a href="https://redd.it/5ayvws">this</a> post on top. The post is good, and interesting because the project that the author links to is mine.</p> <p>After the WTF moment. I calmed down and just realized what few innocent words can do. They broke my heart.</p> <p>I thought the point of open sourcing project on github is to make the project even more better, by accepting criticism the fix the issues and improve. Now it looks like I made a mistake sharing what I believe was worthy sharing. </p> <p>I also thought using vim-go, with all the linting and all those tool to make the code idiomatic was enough, now it looks it isn&#39;t.</p> <p>I also thought extensive testing, and documentation will make the code idiomatic, it looks like I was wrong.</p> <p>I thought reading the standard library, and adopt the good gems I uncovered there will make my code idiomatic, it looks like I was wrong too.</p> <p>My question is , what is idiomatic go?</p> <p>I&#39;m confused, and definitely heart broken.</p> <p><strong>UPDATE</strong></p> <p>Thanks for the constructive comments and advice.</p> <p>I realized I over reacted. And it was someone&#39;s opinion . Which doesn&#39;t represent the Golang community. </p> <p>I&#39;m now looking forward to writing more Go code( hopefully more idiomatic this time) . </p> <hr/>**评论:**<br/><br/>npyde: <pre><p>Don’t be heartbroken. If thousands like your package, you are obviously doing something useful.</p> <p>For non-idiomatic code: I poked around, couldn’t find anything that caught my eye as terrible. Something I personally would refactor:</p> <ol> <li><p>I would create sub-packages, e.g. instead of calling utron.NewModel() or utron.NewModelWithConfig() I would put the model into its own package (sub-package of utron) and call it with models.New() and models.NewWithConfig().</p></li> <li><p>I don’t see a reason why App.Set should accept an interface. I could pass anything into it but internally it only accepts certain types and throws anything else away silently. Yes, the doc comment makes it clear what it accepts but it doesn’t prevent the programmer from making a mistake. SetModel, SetController etc. is more meaningful and the compiler can catch errors early.</p></li> </ol> <p>I think you should ask the author to point out what he thinks is your egregious non-idiomatic Go code.</p></pre>gernest_: <pre><p>Thanks for the advice.</p> <p>There is a lot of areas for improvement. Including the ones you pointed out.</p></pre>sno6: <pre><p>Definitely don&#39;t beat your self up over the comments, I read the original post and had a similar reaction to you. To me, idiomatic Go is cut into two at least two sections, firstly the style/format of your code, which is handled by tools such as gofmt, govet, golint etc. But also, the structure of your project, and understanding both the power of the standard library (what it can do for you, and how to use its powerful features such as interfaces) as well as not trying to re-invent the wheel, but to replace the wheel with something stronger, which still cooperates with the car around it (middleware vs a full web framework that replaces routing etc)</p></pre>FIuffyRabbit: <pre><blockquote> <p>If thousands like your package, you are obviously doing something useful.</p> </blockquote> <p>That&#39;s arguable. Iris has thousands of stars but nearly no one uses it (according to imports and vendors) and the author steals code. </p> <p>I&#39;m not sure if the same could be said for utron but it doesn&#39;t look like bad code. </p></pre>ofpiyush: <pre><p>I&#39;m not qualified enough to say what idiomatic go is but I love the fact that you overcame the fear and pain to share your feelings and ask for help despite the negativity thrown your way.</p> <p>We often ignore the fact that the programmer on the other end is a person with feelings, good on you to speak up and ask for help. And If you&#39;re not already, you will definitely become a good programmer with this attitude. Cheers.</p></pre>1s44c: <pre><p>This is the best comment in this tread.</p></pre>Arcaire: <pre><p>You know when you say a word so much that you suddenly don&#39;t recognise it anymore? That&#39;s me and &#34;idiomatic&#34; with how much it&#39;s slung around every Go community.</p></pre>chewxy: <pre><p>Semantic satiation</p></pre>cmmn_nighthawk: <pre><p>I&#39;m not going to comment on the code. Looks like other people have done a nice job of that already :)</p> <p>To me, the take away is--with more visibility comes higher levels of criticism. That is, this is the price you have to pay for having 1500+ Github stars.</p> <p>DHH wrote Rails, which has deliveres $MM of value to companies, allowed quicker prototyping, and provided an easier onramp for 1,000s of new developers. People <em>love</em> to tell him how slow and shitty it is--every day for over a decade. Taylor Swift writes music that makes people happy, and thousands of people just fucking hate her. Last example, this is one of my favorite tweets: <a href="https://twitter.com/jashkenas/status/684399026939260929">https://twitter.com/jashkenas/status/684399026939260929</a>. Literally hate mail, for putting so many hours into open source.</p> <p>It will always be the loud minority vs the silent majority. I&#39;d try not to be heartbroken. And if that doesn&#39;t work, I wouldn&#39;t share you code. This problem isn&#39;t going away and only gets worse with scale.</p> <p>Good luck out there!</p></pre>weberc2: <pre><p>I wouldn&#39;t sweat it too much. That post represents the opinion of its author only, and I have no reason to believe he is any more an authority on Go and its idioms than you or I.</p></pre>knotdjb: <pre><p>Witch hunts are a motherfucker.</p></pre>schumacherfm: <pre><p>IMHO unidiomatic code is:</p> <p><a href="https://github.com/gernest/utron/blob/master/config.go#L66">https://github.com/gernest/utron/blob/master/config.go#L66</a> JSON, TOML, YAML, HCL: Too many imported packages where maybe only one gets used. Let the developer register its decoder by fulfilling an interface or outsource those case statements into its own separate packages.</p> <p><a href="https://github.com/gernest/utron/blob/master/config.go#L106">https://github.com/gernest/utron/blob/master/config.go#L106</a> No need to use reflect here. There are some packages who do the same for the ENV as for a file. Same pattern as above but now include maybe an order how multiple decoders gets processed to overwrite variables.</p> <p><a href="https://github.com/gernest/utron/blob/master/context.go#L133">https://github.com/gernest/utron/blob/master/context.go#L133</a> <a href="https://github.com/gernest/utron/blob/master/utron.go#L185">https://github.com/gernest/utron/blob/master/utron.go#L185</a> Empty interface in argument only for encoding/decoding</p> <p><a href="https://github.com/gernest/utron/blob/master/models.go#L9">https://github.com/gernest/utron/blob/master/models.go#L9</a> The developer can import the SQL driver ... just let it panic if s/he forgets it.</p> <p><a href="https://github.com/gernest/utron/blob/master/utron.go#L12">https://github.com/gernest/utron/blob/master/utron.go#L12</a> I&#39;m not a fan of package globals. The developer can instantiate itself the app.</p> <p><a href="https://github.com/gernest/utron/blob/master/view.go#L21">https://github.com/gernest/utron/blob/master/view.go#L21</a> Should be an interface to use any rendering engine but use html/template as the default one if none has been set during init.</p> <p>So far my advice. Take that with a grain of salt .... I can also be horribly wrong about my view of idiomatic Go code.</p></pre>Robonia: <pre><blockquote> <p><a href="https://github.com/gernest/utron/blob/master/utron.go#L185" rel="nofollow">https://github.com/gernest/utron/blob/master/utron.go#L185</a> Empty interface in argument only for encoding/decoding</p> </blockquote> <p>So in your opinion, should there be explicit setters for for each field of the App struct? </p></pre>JokerSp3: <pre><p>I would say that is more idiomatic than a &#39;magical set all function&#39;</p></pre>Robonia: <pre><p>I can see that, just seems a bit verbose to have an individual setter for each. I really enjoys Swift&#39;s method for handling setters known as <a href="https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID262" rel="nofollow">Property Observers</a>. </p></pre>JokerSp3: <pre><p>I think in this case its the &#39;more verbose sometimes makes code more clear&#39; type of situation.</p></pre>andrefsp: <pre><p>HI there. Good comment. </p> <p>I wanted to ask why is it you are not a fun of package globals? </p> <p>That is a pattern I use for dependencies that I want to be able to mock easily, or objects where I want to have control over concurrency. </p> <p>Databases connections and service clients are two of those examples. </p> <p>Database connection pools is a good example of a single object that keeps track of all the available connections and delegates to individual requesting go routines.</p> <p>Service clients as well. For testing purposes you might want to mock them easily to avoid real calls to a certain service. </p> <p>I&#39;m aware using dependency injection facilitates much more flexible testing but package level objects with an initializer we can achieve the same. </p> <p>I&#39;m just trying to understand why is it not idiomatic. </p> <p>Thanks in advance :) </p></pre>barsonme: <pre><p>Also why range over map([]struct)? Use a for loop.</p></pre>YEPHENAS: <pre><ul> <li>Go Code Review Comments: <a href="https://github.com/golang/go/wiki/CodeReviewComments">https://github.com/golang/go/wiki/CodeReviewComments</a></li> <li>Go proverbs: <a href="https://go-proverbs.github.io">https://go-proverbs.github.io</a></li> <li>Effective Go: <a href="https://golang.org/doc/effective_go.html">https://golang.org/doc/effective_go.html</a></li> </ul></pre>TeranNotTerran: <pre><p>I&#39;m sorry that you feel this way. I think that I would, too.</p> <p>I think the author was wanting to find an option that&#39;s a bit more &#34;go&#34; (which I can&#39;t evaluate and tell you if that&#39;s the case or not). When you are looking at libraries as just libraries and don&#39;t know the authors, it&#39;s really easy to be critical. If I&#39;m rolling through a list of libraries I need, I throw a lot of them out after a few seconds of looking them over. I guess it&#39;s like opening up a tool box and not being able to clearly see the tools. You still want the best one, there&#39;s a lot of them, and you don&#39;t have the time to actually figure out what you want.</p> <p>My most-starred project has a tenth of the stars and probably has a lot more that you could complain about. Definitely keep developing it and working on it, if that&#39;s what you want to do. I hope more people will continue with you to improve it, but there&#39;s a reason it&#39;s as starred as it is. I, and I hope most, understand that you did this work for free, were open enough to share it, and no one can ask for more.</p></pre>egonelbre: <pre><p>Yes, it may not always be nice when somebody bashes your work. But I&#39;ve found that when someone completely destroys my arguments or points out significant flaws -- I end up learning much more than just building things casually... so in the end I&#39;ve come to enjoy the process, there&#39;s always something you can learn from those situations.</p> <p>Now to the subject matter: whether something is idiomatic is definitely less important than whether it&#39;s valuable. If people get good value from it, great, you&#39;ve done something more useful than many other projects. For example martini project was unidiomatic, something that the author realized himself, but people did build cool stuff with it nevertheless.</p> <p>Now, whether projects are idiomatic/unidiomatic are not necessarily a good/bad thing. For example I wouldn&#39;t want to write &#34;idiomatic&#34; code in Java, because the common idioms are often way too verbose. I would also use more inner classes and larger files; than is recommended. &#34;Unidiomatic&#34; means it&#39;s more difficult to read for usual users...</p> <p>There&#39;s also the other aspect, whether the &#34;idiomatic style&#34; results in good architecture and code. From personal experience I would say that the Go &#34;idiomatic style&#34; definitely has this property. It heavily leans into readable and understandable code -- but not necessarily concision.</p> <p>I&#39;ll try to condense &#34;idiomatic Go&#34; to a few ideas (of course people may agree/disagree with my list):</p> <ol> <li>No stutter.</li> <li>No ambiguous words. (<code>models</code> as the top-level package says nothing useful)</li> <li>Clear value.</li> <li>Concrete over abstract.</li> <li>Depend on interfaces, return structs.</li> <li>Make hard decisions. Don&#39;t have 100 ways of doing something.</li> <li>gofmt, golint.</li> <li>And more <a href="https://go-proverbs.github.io/" rel="nofollow">https://go-proverbs.github.io/</a></li> </ol> <p>For further reading on structuring applications:</p> <ul> <li><a href="https://codegangsta.io/blog/2014/05/19/my-thoughts-on-martini/" rel="nofollow">https://codegangsta.io/blog/2014/05/19/my-thoughts-on-martini/</a></li> <li><a href="https://github.com/marcusolsson/goddd" rel="nofollow">https://github.com/marcusolsson/goddd</a> (and the associated blog posts)</li> <li><a href="https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1#.uec37ltci" rel="nofollow">https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1#.uec37ltci</a></li> <li><a href="https://forum.golangbridge.org/t/comparing-the-structure-of-web-applications/1198" rel="nofollow">https://forum.golangbridge.org/t/comparing-the-structure-of-web-applications/1198</a></li> <li><a href="https://groups.google.com/forum/#!msg/golang-nuts/1z5kL5FCDdU/--Iox7PSAwAJ" rel="nofollow">https://groups.google.com/forum/#!msg/golang-nuts/1z5kL5FCDdU/--Iox7PSAwAJ</a></li> </ul> <p>Unfortunately a full review of <code>utron</code> would take too much time, so I&#39;m going to give the general impression I got. The top-level looks overly generic -- it is unclear what is the win over other projects (points 3, 4). The example application uses generic top-level packages (points 2, 3, 4). There is only one example, and that itself is trivial -- show also business logic (e.g. <a href="https://revel.github.io/samples/booking.html" rel="nofollow">https://revel.github.io/samples/booking.html</a>, I&#39;m not saying I like the code, but I do like the example).</p></pre>rco8786: <pre><p>Part of sharing your work publicly is implicitly opening it up to criticism. This is true of anything you decide to share with the world whether it&#39;s a blog, a tweet, art, a company, code, etc. </p> <p>Everyone has their own opinion and there&#39;s no way you can make everyone&#39;s opinion of your work positive. Don&#39;t worry about it. </p> <p>Hey, if that person hadn&#39;t linked to your project I never would have even heard about it!</p></pre>: <pre><p>[deleted]</p></pre>rco8786: <pre><blockquote> <p>there constructive criticism and slandering.</p> </blockquote> <p>Yep, and publicly sharing work opens yourself up to both. Other thread guy has an opinion and shared it. The fact that the opinion wasn&#39;t a very nice one doesn&#39;t matter.</p></pre>ballagarba: <pre><p>Now you&#39;ve made me sad too :&#39;( Since the guy in the other post didn&#39;t even mention <em>why</em> he thought it was un-idiomatic, it&#39;s probably just jealousy.</p> <p>This is <em>my</em> take on what people generally mean when they think of idiomatic Go:</p> <ul> <li>Use gofmt, no exceptions.</li> <li>Avoid using <code>interface{}</code> and reflection.</li> <li>Stick to what&#39;s available in the standard library as much as possible.</li> <li>Create small interfaces, like <code>io.Writer</code> and <code>io.Reader</code>. They&#39;re basically the best thing since sliced bread.</li> </ul> <p>But perhaps more important. If you ask 10 different people what idiomatic Go is, you&#39;ll get 10 different answers. So don&#39;t beat yourself up over it!</p></pre>Robonia: <pre><p>Why avoid reflection? I&#39;m new to the language, just curious.</p></pre>PsyWolf: <pre><p>Check out <a href="https://go-proverbs.github.io">https://go-proverbs.github.io</a> and the video linked on that page. Specifically these 2</p> <ul> <li>Clear is better than clever.</li> <li>Reflection is never clear.</li> </ul></pre>therocketofpoop: <pre><p>Reflection does have performance and readability implications, but it is a tool to be used when necessary. One does not use a screwdriver for nails or a hammer for screws.</p> <p>Now, as advice, I will tell you to disregard those who say NEVER EVER do x with a language. Those who say that have limited experience applying the language in limited use cases. There are situations where there is no choice but to do x. Many standard library packages do use reflection.</p></pre>piva00: <pre><p>Reflection is expensive and hides details. I&#39;m not currently working with Go and had limited experience so far (some 6 months only) with it but that&#39;s a trueism for any kind of language: try not to hide too much behind &#34;magic&#34;, and reflection is a kind of it.</p> <p>Also using too much reflection opens your code to bugs that could/should have been caught at compile-time but ends up exploding at runtime.</p> <p>Keep it simple.</p></pre>quiI: <pre><p>You&#39;re giving up compiler safety</p></pre>__crackers__: <pre><p>I think you&#39;re taking the whole thing a bit too much to heart.</p> <p>I mean, this isn&#39;t Rob Pike ripping on your code. What evidence do you have that <a href="/u/m3wm3wm3wm">/u/m3wm3wm3wm</a> is any kind of authority on Go, and not just some random Internet blowhard?</p> <p>And by extension, why should you assign his/her opinion of your code any weight?</p> <p>Surely, thousands of GitHub stars says a whole lot more than an isolated dissing by some random redditor. It&#39;s not like they all starred your project so they can come back and shit on you when they&#39;re having a bad day, is it?</p></pre>natefinch: <pre><p>Obviously, over 1600 people thought your project was interesting enough to star it. That&#39;s pretty impressive.</p> <p>I think it&#39;s unfortunate that the other thread used your project as an example of a project that doesn&#39;t deserve the stars it gets. The author of that thread shouldn&#39;t have named names and just talked more generally about projects that seem to get more attention than he personally thinks they deserve.</p> <p>Stars are stars. Unless someone is using a bot to create github accounts and fake the stars, you deserve whatever you have. </p> <p>Don&#39;t let one person&#39;s opinion get you down.... you&#39;ve obviously put a ton of work into Utron and that deserves a lot of respect.</p></pre>goomba_gibbon: <pre><p>That&#39;s what I don&#39;t understand. The point was a general one, an interesting one even. OP didn&#39;t need to shame a specific repo to illustrate the point.</p></pre>goomba_gibbon: <pre><p>I thought the standard library itself contained various different styles. I&#39;m sure I remember reading this but can&#39;t remember where.</p> <p>For the record, I think idiomatic code is good if we are talking about keeping a consistent style. What&#39;s more important is writing stuff and putting it out there. Keep it up!</p></pre>1s44c: <pre><p>&#39;Idiomatic&#39; means &#39;what I would do&#39; with the implication that everything else is wrong. It&#39;s a corrosive concept that has damaged the ruby world. Why do ruby programmers use &#39;do ... end&#39; loops when ruby has perfectly good curly braces? Because it&#39;s idiomatic and for no other reason.</p> <p>Golang doesn&#39;t need idiot-matic programming. No language needs idiot-matic programming.</p></pre>cep221: <pre><p>My personal view is idiomatic code for any language is code in the style of its standard library.</p></pre>mrmylanman: <pre><p>To be honest I read the other post and thought it was very off base. It sounded like most of the issues he had with it were scenarios he filled in himself (like how he assumed you went to shows and solicited github stars? I don&#39;t know if you do that. I also wouldn&#39;t care if you did).</p> <p>So I wouldn&#39;t say much of what he was complaining about anything technical in nature. One of his original points was that your project was a month old which wasn&#39;t even true (he was mistaken). So I think your project was just unfortunate enough to be the example he cited.</p> <p>Sounds like your code is in decent shape and your heart is in the right place, so keep soldiering on!</p></pre>epiris: <pre><p>The idiomatic argument is just an excuse for mad people to be mad. For every person who is busy being &#34;hurt&#34; about what you are doing, many more normal people are appreciating the effort of someone who shares a common interest with them. I don&#39;t care what your Go code looks like, I will read it. I will read it within the same time give or take as some uptight mad dudes idiomatic code. Go doesn&#39;t let you send me into a black hole by design.</p> <p>My most starred repo was something I made two years ago to play with Go generate, it&#39;s full of giant switch statements and is the least idiomatic thing ever made. You wanna know what I say about that? Lollllllllllllll</p> <p>Don&#39;t care. Code, have fun, get better, share, learn. Don&#39;t take criticism to heart, take it to the bank, get better and just keep accumulating all the experience.</p> <p>Your project is awesome and you should keep working at it. Haters gonna hate, man.</p></pre>thepciet: <pre><p>Would it be accepted as implementation code in the standard library by the Go maintainers?</p></pre>GoTheFuckToBed: <pre><p>I did not read. But maybe add &#34;what it is not&#34; to the readme, so people don&#39;t confuse it for something it is not.</p></pre>shovelpost: <pre><p>The best way to find out is to ask <a href="/u/m3wm3wm3wm" rel="nofollow">/u/m3wm3wm3wm</a>.</p></pre>PHPDevloper: <pre><p>I don&#39;t think it&#39;s about the code being unidiomatic. It&#39;s about envy. Everybody nowadays has their own Go framework. And, of course, everybody is sure theirs is the most idiomatic, truly conventional, and the best of the best. But not everybody&#39;s framework has GH <del>karma</del> stars. I think, somewhere deep deep in subconsciousness I am envy, too. At least I was for sure.</p> <p>P.S.: Let&#39;s look at the number of downvotes I&#39;d get. All of those are the envy people I&#39;m talking about.</p></pre>1s44c: <pre><blockquote> <p>P.S.: Let&#39;s look at the number of downvotes I&#39;d get. All of those are the envy people I&#39;m talking about.</p> </blockquote> <p>I was going to upvote you but now I feel like you are trying to reverse psychology me into it.</p></pre>thesilentwitness: <pre><p>My only suggestion would be to stop using Gorm, it&#39;s not very good, to say the least: <a href="https://github.com/vattle/sqlboiler#benchmarks" rel="nofollow">https://github.com/vattle/sqlboiler#benchmarks</a> -- literally any other ORM is a better fit.</p></pre>upboatact: <pre><p>Ahh drama!</p> <p>Just what I needed, have an upboat</p></pre>

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

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