Why's even the most basic stuff so complicated?

agolangf · · 169 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So, I decided to try Go, starting with the basics of course.<br/> And the simplest way I found to read a line from stdin and print it back is this:</p> <pre><code>package main import (&#34;fmt&#34; &#34;bufio&#34; &#34;os&#34; &#34;strings&#34;) func main() { var name string reader := bufio.NewReader(os.Stdin) fmt.Println(&#34;What is your name?&#34;) name, _ = reader.ReadString(&#39;\n&#39;) name = strings.TrimSpace(name) fmt.Printf(&#34;Hi, %s!\n&#34;, name) } </code></pre> <p>And it took half an hour just to puzzle these together. I still can&#39;t understand why fmt.Scanln doesn&#39;t work (its documentation says it reads until a newline, so why doesn&#39;t it do that?) and have no idea what&#39;s going on above in lines 11 and 13, and if I haven&#39;t already known some C, I wouldn&#39;t be able to figure out why writing <em>&#34;\n&#34;</em> in reader.ReadString() didn&#39;t work in line 13. But the fact that I need 4 imports just to read and write a string seems to be a huge overkill to me.<br/> Does Go get any easier later or does everything need so much work?</p> <hr/>**评论:**<br/><br/>nohoudini: <pre><p>Go is simple but repetitive. Go has taught me how the Single Responsability Principle &amp; dependency injection is used well. I was in the same boat and thought it&#39;s a very overkill but after some time you realize that the components are well split and make sense.</p></pre>nwss00: <pre><p>If you want a language where you don&#39;t have to care much about implementation details then check out Ruby.</p> <p>Ruby solves things in 1 line and whenever you ask why, you&#39;re always given a strange look and reply, &#34;It just works. Forget about the nitty-gritty and move on.&#34;</p></pre>dimitrios_gopher: <pre><p>In ruby, it is really easy for a bad programmer to write complicated code and hide many flaws or bugs.</p> <p>In Go, it is really easy for a bad programmer to write simple code and their errors will be glaringly obvious, which can be easily spotted and fixed.</p> <p>Anyways, still recovering from the horrors of my Rails days. Magic sucks. Screw magic. </p></pre>mgutz: <pre><p>Or Perl! But yeah, the hardest part of learning Go is unlearning what you&#39;ve learned from other languages. Once you do, Go becomes a rewarding experience. </p> <p>As for imports, you rarely have to manage those. Editors with Go support do that automatically. It&#39;s no different than Java, C# in that sense.</p></pre>oefig: <pre><blockquote> <p>But the fact that I need 4 imports just to read and write a string seems to be a huge overkill to me.</p> </blockquote> <p>Four imports to do it the way you want to do it. Really, you just need <code>fmt</code>, and <code>strings</code> if you want to use <code>strings.TrimSpace</code>.</p> <pre><code>package main import ( &#34;fmt&#34; &#34;strings&#34; ) func main() { var name string fmt.Println(&#34;What is your name?&#34;) fmt.Scanln(&amp;name) fmt.Printf(&#34;Hi, %s!\n&#34;, strings.TrimSpace(name)) } </code></pre> <blockquote> <p>I still can&#39;t understand why fmt.Scanln doesn&#39;t work (its documentation says it reads until a newline, so why doesn&#39;t it do that?)</p> </blockquote> <p>If you posted your code we could probably tell you why it doesn&#39;t. As demonstrated above, <code>fmt.Scanln</code> does exactly that.</p></pre>OctaviaPinfold: <pre><p>Scanln stops scanning at the first space.</p></pre>PM_ME_MY_REAL_MOM: <pre><p>This is what the <a href="https://golang.org/pkg/fmt/#Scan" rel="nofollow">docs</a> say about <code>fmt.Scan</code> and <code>fmt.Scanln</code>:</p> <blockquote> <p>Scan scans text read from standard input, storing successive space-separated values into successive arguments. Newlines count as space. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why.</p> </blockquote> <hr/> <blockquote> <p>Scanln is similar to Scan, but stops scanning at a newline and after the final item there must be a newline or EOF.</p> </blockquote> <hr/> <p>So as documented, <code>fmt.Scanln</code> is reading from stdin, separating the input by spaces, and storing the results in the arguments provided. Since you only provided one argument, only the first word was returned. I think <code>fmt.Scanln</code> is not the most suitable for reading a single line from stdin, if you don&#39;t need it tokenized.</p> <p>You&#39;re looking for a single string of arbitrary length that ends with a newline, and you want to trim the spaces on the ends of that string. I&#39;d say your original implementation is ideal.</p> <p>Yes, Go is a verbose language. I wouldn&#39;t say that makes it <em>difficult</em>; so your question &#34;Does it get easier?&#34; is, I don&#39;t know. I come from the Ruby world and find the explicitness of Go refreshing, but many don&#39;t, and Go has other similar shortcomings that will turn those developers away.</p> <p>Best of luck to you!</p></pre>OctaviaPinfold: <pre><p>Oh, so it also creates multiple results separated by spaces. That wording was a bit confusing, I read the documentation again and again but kept assuming Scanln can read multiple lines like Scan reads multiple &#34;words&#34;.</p></pre>metamatic: <pre><p>It&#39;s scanning multiple values from a line, rather than scanning lines.</p> <p>Similarly with sql.Scan, it&#39;s scanning multiple values from a row rather than scanning rows. So at least there&#39;s some consistency.</p></pre>geodel: <pre><p>You really need to move to NodeJS. Put a few dozen plugin and code will write itself.</p></pre>kardianos: <pre><p>Go isn&#39;t optimized for one-liners. Writing a single line of code doesn&#39;t amount to a single unit of work.</p> <p>Go has good readability. Let me read your program back you you:</p> <ol> <li>Create a buffered reader from stdin.</li> <li>Print to std out a question.</li> <li>Read text from the buffer, stop reading at the newline (enter key).</li> <li>Remove leading and trailing spaces from the answer.</li> <li>Print the answer out to you.</li> </ol> <p>I&#39;m not sure what you&#39;re expecting. If you&#39;d like to use the fmt package, you could do the following:</p> <pre><code>package main import ( &#34;fmt&#34; &#34;log&#34; &#34;strings&#34; ) func main() { fmt.Println(&#34;my question?&#34;) var ans string _, err := fmt.Scanln(&amp;ans) if err != nil { log.Fatal(&#34;scan err&#34;, err) } fmt.Printf(&#34;my ans: %q\n&#34;, strings.TrimSpace(ans)) } </code></pre> <p>Make sure you read the docs; don&#39;t assume something is intended to work how you think it should work, verify your assumptions with the docs.</p></pre>OctaviaPinfold: <pre><p>With this I get </p> <pre><code>2017/10/29 20:58:08 scan errexpected newline exit status 1 </code></pre> <p>Edit: It works only if there&#39;s no space in the input.</p></pre>wavy_lines: <pre><blockquote> <p>Does Go get any easier later or does everything need so much work?</p> </blockquote> <p>I don&#39;t think it gets &#34;easier&#34; in any sense except that you get used to it.</p> <p>Go is verbose. It&#39;s probably less verbose than C or Java, but it&#39;s still verbose if you&#39;re coming from a python background.</p> <p>Python is optimized for short scripts. Go is not optimized for that. Go discourages creating many layers of abstraction. </p></pre>shovelpost: <pre><p>Scanning from the standard input, while it sounds trivial, it can be surprisingly tricky because it has a lot of corner cases. It&#39;s not much better in other languages either. Don&#39;t let it discourage you.</p></pre>

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

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