Short code review request

polaris · · 394 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi all,</p> <p><a href="https://play.golang.org/p/LaTzw5nEtO" rel="nofollow">https://play.golang.org/p/LaTzw5nEtO</a></p> <p>This is my first foray into Go (I&#39;m a C dev by day) and I&#39;ve got no one for a code review, if anyone has 2 minutes to look through I&#39;d be very appreciative of some feedback</p> <p>The code is only short, it reads in 4 CSV files that contain DB format data (tables, columns, primary keys and indexes) and produces a JSON file with it all together.</p> <p>The goal is to then use this to be able to easily put together a data dictionary in a static site with something like angular eventually.</p> <p>Thanks, Daniel.</p> <hr/>**评论:**<br/><br/>fr4nk3n: <pre><p>you can write the following:</p> <pre><code>v, ok := indexesMap[table.Name] if ok == true { tables[i].Indexes = v } </code></pre> <p>like this:</p> <pre><code>if v, ok := indexesMap[table.Name]; ok { tables[i].Indexes = v } </code></pre> <p>I would make sure an index of an array/slice exists before you try to access it.</p> <p>If you haven&#39;t already take a look at <a href="https://golang.org/doc/effective_go.html" rel="nofollow">Effective Go</a>.</p> <p>If these are very large csv files, maybe take a look at the <a href="https://golang.org/pkg/bufio/#example_Scanner_lines" rel="nofollow">bufio package</a>.</p></pre>dphobson: <pre><p>Thanks.</p> <p>That&#39;s a nice little tweak, I remember seeing that in the tour now you&#39;ve pointed it out.</p> <p>The files are only a few hundred lines long so I think it&#39;s safe to read it all in as one at the moment, I&#39;ll have a look at bufio for future though.</p></pre>Frakturfreund: <pre><p>This is just a stylistic nitpick, but instead of this C-style code</p> <pre><code>if input.filename == &#34;tables.csv&#34; { fileData = []byte(tables_csv) } else if input.filename == &#34;columns.csv&#34; { fileData = []byte(columns_csv) } else if input.filename == &#34;indexes.csv&#34; { fileData = []byte(indexes_csv) } else if input.filename == &#34;pks.csv&#34; { fileData = []byte(pks_csv) } </code></pre> <p>you should write in Go</p> <pre><code>switch input.filename { case &#34;tables.csv&#34;: fileData = []byte(tables_csv) case &#34;columns.csv&#34;: fileData = []byte(columns_csv) case &#34;indexes.csv&#34;: fileData = []byte(indexes_csv) case &#34;pks.csv&#34;: fileData = []byte(pks_csv) } </code></pre> <p>It’s shorter and looks more clear. Notice that the <a href="https://github.com/golang/go/wiki/Switch" rel="nofollow">Go <code>switch</code> doesn&#39;t need <code>break</code>’s, but has a <code>fallthrough</code> keyword instead</a>.</p></pre>subtlepseudonym: <pre><p>Both code blocks compile to the same code (IIRC) so it&#39;s definitely worth going for readability.</p></pre>dphobson: <pre><p>The switch is definitely clear and I&#39;ll use that in future</p></pre>carsncode: <pre><p>Generally looks OK to me at first glance, but I&#39;ll call out a couple things. I&#39;d put your quiet setting in a global so you don&#39;t have to pass it to your log function every time, since you always pass the same variable in. Unless this is a throwaway app you&#39;ll use twice and never look at again, you should handle errors better than just panicking. Lastly in all the places where you&#39;re instantiating a struct and comment all the fields, dump the comments and use the field labels instead of the short hand format.</p> <p>Hope it helps, good luck with your gophering! Hope you&#39;re enjoying it!</p></pre>dphobson: <pre><p>Thanks.</p> <ul> <li><p>The panic() call was just a copy/paste from another file I was looking at, that should definitely be handled better.</p></li> <li><p>What do you mean by the following? </p></li> </ul> <blockquote> <p>Lastly in all the places where you&#39;re instantiating a struct and comment all the fields, dump the comments and use the field labels instead of the short hand format.</p> </blockquote></pre>Frakturfreund: <pre><p>Instead of instantiating your structs like this:</p> <pre><code>table := ddTables{ row[1], // Tablename row[2], // Tablespace row[4], // Comments []ddColumns{}, // Empty Columns []ddIndexes{}} // Empty Indexes </code></pre> <p>Do it like this:</p> <pre><code>table := ddTables{ Name: row[1], TableSpace: row[2], Comments: row[4], Columns: []ddColumns{}, Indexes: []ddIndexes{}, } </code></pre> <p>The second one is more typesafe: consider someone refactors the <code>ddTables</code> struct and switches the order of <code>Name</code> and <code>TableSpace</code> for consistency with other structs. This will introduce a silent bug in the first code variant, but not in the second (see also <a href="https://golang.org/doc/effective_go.html#composite_literals" rel="nofollow">Effective Go</a>).</p> <p>You can still add comments in the second one, but normally the code should speak for itself.</p> <p>Also note that the final <code>}</code> got it’s own line, and the additional <code>,</code> at the end of the previous line: That’s for clearer diffs.</p></pre>subtlepseudonym: <pre><p>On line 228:</p> <pre><code>tables[i].Columns[j].Primary = v </code></pre> <p>Can be replaced with</p> <pre><code>column.Primary = v </code></pre> <p>And the i and j variables (defined on 221 and 223) can be thrown away because this is the only instance of their use.</p></pre>dphobson: <pre><p>Thanks.</p> <p>I&#39;ve just tried this and it doesn&#39;t appear to work, I changed to the following:</p> <pre><code>// Loop through the table data and populate the primary keys for _, table := range tables { for _, column := range table.Columns { if v, ok := pkMap[string(table.Name+&#34;.&#34;+column.Name)]; ok { column.Primary = v } } } </code></pre> <p>The code runs fine but the Columns.Primary data in tables isn&#39;t populated after the loop, is the table/column data in these ranges a copy of the current tables instance or is it a reference to it?</p> <p>Changing back to this still works and takes into account some of the other suggestions above:</p> <pre><code>// Loop through the table data and populate the primary keys for i, table := range tables { for j, column := range table.Columns { if v, ok := pkMap[string(table.Name+&#34;.&#34;+column.Name)]; ok { tables[i].Columns[j].Primary = v } } } </code></pre></pre>subtlepseudonym: <pre><p>All of the variables on the left side of the range statement (i, j, table, column) are references. My understanding was that &#39;column.Primary&#39; would serve as shorthand for &#39;column-&gt;Primary&#39; though. </p> <p>After poking through the spec a bit, it seems that &#39;column&#39; is only preserved within the scope of the for loop because you used short variable declaration (:=). </p> <p><a href="https://golang.org/ref/spec#For_statements" rel="nofollow">https://golang.org/ref/spec#For_statements</a></p></pre>

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

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