<p>An bad title I know, basically it comes down to these two different situations.</p>
<p>First if we have a create method which accepts a pointer to the model:</p>
<pre><code>func Create(model *Model) error {
model, err := db.Insert(model)
if err != nil {
return err
}
return nil
}
</code></pre>
<p>Second we have a method which also returns the pointer</p>
<pre><code>func Create(model *Model) (*Model, error) {
model, err := db.Insert(model)
if err != nil {
return nil, err
}
return model, nil
}
</code></pre>
<p>I was erring towards the second signature because it lets you use a literal as the argument to create and still have a reference at the end of the method.</p>
<p>Views?</p>
<hr/>**评论:**<br/><br/>tmornini: <pre><p>Why not:</p>
<p>func (model *Model) Create() error</p></pre>ROFLLOLSTER: <pre><p>Because then you can't do:</p>
<pre><code>model, err := Create(&Model{fields...})
</code></pre></pre>tmornini: <pre><p>Fair enough</p>
<pre><code>func (model *Model) Create() (*Model, error)
</code></pre>
<p>Allows</p>
<pre><code>model, err := &Model{fields ...}.Create()
</code></pre></pre>shovelpost: <pre><p>I don't think it is is a good idea to add database logic to your application's structs.</p></pre>tmornini: <pre><p>I would have agreed with that in the past.</p>
<p>Now that I'm thinking purely in terms of HTTP microservice systems, I find there's no benefit in the additional complexity.</p>
<p>OP code implied the Create func was already in the Model struct's package.</p>
<p>EDIT: 180 degree turn around after thinking it through.</p></pre>ROFLLOLSTER: <pre><p>They are actually in different packages, just wrote it that way for brevity because I'm on mobile.</p></pre>tmornini: <pre><p>All good!</p></pre>shovelpost: <pre><p>I believe there is a 3rd option:</p>
<pre><code>func Create(u User) (User, error) or func Create(u User) (*User, error)
</code></pre>
<p>You pass a copy with only the required values filled like say <code>Name</code> and you return a brand new user that contains the rest like <code>ID</code> and <code>Created</code>.</p>
<p>I think it makes a little more sense than:</p>
<pre><code>func Create(u *User) (*User, error)
</code></pre>
<p>Because if we are passing a pointer then why return it? Is it the same one? If it is then why not modify the original one instead? Of course there is still the argument that <code>User</code> might be big and we do not wish to copy it. So...</p>
<p>I think my favorite option is :</p>
<pre><code>func Create(u *User) error
</code></pre>
<p>Where you pass a pointer and after the function ends successfully if we inspect the fields of <code>u</code> the fields like <code>ID</code> and <code>Created</code> have been filled with the values from the database. It feels a little more "lightweight" to me and the fact that you pass down a pointer it means that the function is planning to modify its values.</p>
<p>In the end I don't think it matters too much. Just be consistent across the codebase.</p>
<p>P.S. I know it was an example but I detest seeing things like <code>models.Model</code> with <code>models</code> being the worst part.</p></pre>dasopranos: <pre><p>I like the second one. It makes the code smaller which is always good, and IMHO it makes it more readable too.</p>
<p>Infact I go even futher, i would do:
<a href="https://play.golang.org/p/6e_Er9PtdH" rel="nofollow">https://play.golang.org/p/6e_Er9PtdH</a></p>
<p>(sorry i couldnt get reddit code formatting to work)</p></pre>tmornini: <pre><p>You're headed down the road to creating your own ORM.</p>
<p>The path to hell is paved with good intentions!</p></pre>dasopranos: <pre><p>I don't see it. What I see is the orthognality of the DB and Model concepts in my program.</p>
<p>"Simplicity comes from orthogonality and predictability." -- Rob Pike</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传