Code Review

agolangf · · 869 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi Guys, </p> <p>I&#39;m learning go and am building a sample console app.</p> <p>It&#39;s still a work in progress but I was hoping you could take a look when you get chance and give me your feedback. </p> <p>You can find it here: <a href="https://github.com/donpisci/BusRoute" rel="nofollow">https://github.com/donpisci/BusRoute</a></p> <p>Thanks in advance!</p> <hr/>**评论:**<br/><br/>bketelsen: <pre><p>In no particular order: 1) generally Go apps don&#39;t have capital letters in the import path. BusRoute might do strange things for people with case sensitive file systems Same with all file names. No caps please. 2) Use go style comments and your godoc generated documentation will look good. ( <a href="http://blog.golang.org/godoc-documenting-go-code" rel="nofollow">http://blog.golang.org/godoc-documenting-go-code</a> ) 3) No need to export the Print type, it&#39;s a self contained 4) Love that you used busroute.CommandError. Named errors are great. 5) You declared interfaces (like traveller) but I don&#39;t see them used in code anywhere. I would expect you to use the Traveller interface on the bus. Then you could have Passengers and Dogs, for example, both implementing the Traveller interface.</p> <p>Overall great start to Go.</p></pre>izuriel: <pre><p>Right off the bat, in the main.go file I feel you missed an opportunity to fully leverage yoru interface. I would simplify your command generate process to something along the lines of creating a map with your interface and assigning your commands to it.</p> <pre><code>var busrouteCommands = map[string]busroute.Commander{ &#34;print&#34;: NewPrint(), &#34;exit&#34;: new(Exit), &#34;passenger&#34;: busroute.NewPassengerCommand(), &#34;bus&#34;: busroute.NewBusCommand(), &#34;create-database&#34;: busroute.NewCreateDatabaseCommand(), } var helpCommand = new(Help) </code></pre> <p>And the benefit of this, of course, is that parse becomes:</p> <pre><code>func parse(cmd string) busroute.Commander { key := strings.TrimRight(strings.ToLower(cmd), &#34;\n&#34;) if commander, ok := busrouteCommands[key]; ok { return commander } else { return helpCommand } } </code></pre> <p>(Also notice that I changed <code>string(&#39;\n&#39;)</code> to <code>&#34;\n&#34;</code>, I&#39;m sure the Go compiler will optomize this for you but if you want a string, just make one)</p> <p>New additions of command require little more than adding a new entry to the map. If you do need the new addition of commands when you run parse, you can take a similar yet slightly different approach:</p> <pre><code>type CommandDefiner func() busroute.Commander var busrouteCommands = map[string]CommandDefiner{ &#34;print&#34;: func() busroute.Commander { return NewPrint() }, // omitted for brevity } </code></pre> <p>And then your adjustment to parse is to return <code>commander()</code> instead of <code>commander</code>. These are mostly small bits but I thought I would point them out so you were aware of alternative approaches. </p></pre>augorak: <pre><p>I highly recommend the tools &#34;go vet&#34;, &#34;golint&#34; and &#34;goimports&#34;. Lots of the feedback you&#39;ve already gotten would be mentioned/corrected by those tools.</p> <p>I also recommend using a text editor like Sublime (with GoSublime) or Vim (with vim-go) instead of an IDE. Its definitely more common to not use an IDE and you&#39;ll want to see your project the way others will if they fork it.</p> <p>You&#39;ve split your main.go into sections with comments when what I think you really want to do is split those blocks into files.</p> <p>Your &#34;main_test.go&#34; file doesn&#39;t contain any functions that start with &#34;Test...&#34; so you are not leveraging the included test runner ( <a href="http://golang.org/pkg/testing/" rel="nofollow">http://golang.org/pkg/testing/</a> )</p> <p>It is more idiomatic to return an error and let the caller decide what to do than to print it. For example:</p> <pre><code>func loadConnectionString() (Config, error) { content, err := ioutil.ReadFile(&#34;config.json&#34;) if err != nil { fmt.Print(&#34;Error:&#34;, err) } var conf Config err = json.Unmarshal(content, &amp;conf) if err != nil { fmt.Print(&#34;Error:&#34;, err) } return conf, err } </code></pre> <p>Would be written as:</p> <pre><code>func loadConnectionString() (*Config, error) { content, err := ioutil.ReadFile(&#34;config.json&#34;) if err != nil { return nil, err } conf := new(Config) err = json.Unmarshal(content, conf) if err != nil { return nil, err } return conf, err } </code></pre></pre>donpisci: <pre><p>Thank you all for the feedback, I really appreciate it. I&#39;ve incorporated the changes mentioned (not committed yet) and think I am starting to think in more of a &#39;go&#39; way. Although, I have tried declaring variables in C# using &#39;:=&#39; !</p> <p>I think the hardest bit so far has been trying to stay idiomatic as, coming from a C# background, there are number of differences. </p></pre>

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

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