<p>I started playing around with Go about a week ago and I am having a lot of difficulty with producing code that I am happy with. I am a C# developer by trade and have dabbled with various other languages, but Go's lack of traditional OOP is throwing me for a loop.</p>
<p>That being said, I have a few questions:</p>
<p>First, are any articles or anything you suggest I read? </p>
<p>Second, do any of you have a backend web service you've built that is on Github or something? I think it would be very beneficial to see some patterns other users are using. </p>
<p>Third, can you take a look at some basic code I have put together and steer me in the right (or just better) direction?</p>
<p>The actual functionality of my code isn't important. There is a main package that registers the AccountRegister function, but it isn't included.</p>
<p><a href="https://gist.github.com/anonymous/50ab2748ced1cc8ac22c1d33161f0581" rel="nofollow">https://gist.github.com/anonymous/50ab2748ced1cc8ac22c1d33161f0581</a></p>
<p>Thanks for all your help.</p>
<hr/>**评论:**<br/><br/>BraveNewCurrency: <pre><blockquote>
<p>I started playing around with Go about a week ago and I am having a lot of difficulty with producing code that I am happy with.</p>
</blockquote>
<p>Go is not a toy language. Expect to spend more than a week to really understand it.</p>
<blockquote>
<p>Go's lack of traditional OOP is throwing me for a loop.</p>
</blockquote>
<p>It's actually OOP that is throwing you for a loop. Because of inheritance, it's rare that you can copy a class (for a domain object) from one project to the next. With Go, you compose your objects (structs) from isolated sub-objects (structs). It's almost like OOP mix-ins, except go enforces the rule "sub-objects don't know about the larger objects they are embedded in". At first, this seems like a serious limitation. But later, you realize that it forces modular code, and allows really neat re-use. For example, the "Mutex" struct can't know anything about the object it's locking, therefore it can be re-used anywhere.</p></pre>nstratos: <pre><blockquote>
<p>First, are any articles or anything you suggest I read?</p>
</blockquote>
<p>Feel free to check out <a href="https://www.reddit.com/r/golang/comments/56wk4v/structuring_go_api/d8n4axl/" rel="nofollow">this comment</a> which has a collection of some good articles that help with structuring code in a Go project.</p>
<blockquote>
<p>Third, can you take a look at some basic code I have put together and steer me in the right (or just better) direction?</p>
</blockquote>
<p>About your code I think it looks okay. </p>
<p>Something you could improve is to do some better error handling. You could use the technique described in <a href="https://blog.golang.org/error-handling-and-go#TOC_3." rel="nofollow">this article</a> and keep the error handling of all your handlers in one place.</p>
<blockquote>
<pre><code>const (
PasswordMismatch = "PasswordMismatch"
)
</code></pre>
</blockquote>
<p>If you think you'll add more errors later you could use <code>iota</code> like <a href="https://github.com/upspin/upspin/blob/master/errors/errors.go#L68-L117" rel="nofollow">this</a>.</p>
<blockquote>
<p><code>const Debug = true</code></p>
</blockquote>
<p>Another technique you could instead of a debug const is build tags. You could have a function with empty implementation in your normal files and guard that file with <code>// +build !debug</code> and have another file with <code>// +build debug</code> which will contain the debug implementation. Then when you compile with <code>go build -tags=debug</code> the go toolchain will use the debug implementation.</p>
<p>You can see this technique being used in the <a href="https://github.com/upspin/upspin/tree/master/errors" rel="nofollow">Upspin</a> project. Check the <code>debug.go</code>, <code>debug_stub.go</code> and <code>errors.go</code> files. I think it is also a very good project to learn from.</p>
<p>And you can use build tags for all sorts of stuff like for example writing integration tests which since they might have to use a database or some other system you don't want them to run every type you do <code>go test</code> so you use a build tag and run them only with something like <code>go test -tags=db</code>.</p></pre>titpetric: <pre><ol>
<li>You're welcome to read my blog for some focused articles, <a href="https://scene-si.org" rel="nofollow">https://scene-si.org</a>, Go by example is a great all-round reference: <a href="https://gobyexample.com/" rel="nofollow">https://gobyexample.com/</a> - and look at examples in the stdlib documentation, godoc for packages. If it's a back-end service, I'd suggest to get familiar with database/sql and specifically jmoiron/sqlx for MySQL., - just consume anything that's relevant to you,</li>
<li>For a front/backend service, you can take a look at my <a href="https://github.com/titpetric/pendulum" rel="nofollow">titpetric/pendulum</a>, it provides a simple web api for a front-end VueJS app (file browser + static file editor).</li>
</ol>
<p>In regards to your example code, I would bind the functions around a struct, ie, <code>Account</code>, <code>func NewAccount() Account</code>, and handle complete API endpoints for accounts here. In the example project above I do the same, albeit I just use a generic "API" name to group individual endpoints. While not a requirement, I prefer this over creating a package. It's sort of a trade off.</p>
<p>If you have a small project, grouping functions around a struct is good. If you have a big project, you'll move onto packages for cleaner separation. If you have a small project (microservice), you might implement a flat structure for endpoints, like you did. If this project grows - you might want to separate the http interface away from the actual "native" api. I do this in the Pendulum API above, calls like <code>StoreHandler</code> invoke a more native API <code>Store</code> hidden behind it. It separates the HTTP logic and response structures away from the more internal API which could be used as a package import.</p>
<p>You'll learn the most by writing a lot of code. The above example was written in about 4 hours, and with such time constraints I'm sure it's better than if I had a very long time to write it (of course, also not perfect but I only have minor thoughts about how I would more strictly separate the HTTP API and the internal API).</p>
<p>Keep on coding :)</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传