<p>Hey, I'm new-ish to Go and I'm still struggling with it not being OOP (that's what's been hammered into my brain since forever). I've been struggling with modeling my stuff right, but I just can't make it work. </p>
<p>Simply put, I'm building a REST API. let's say you can request an item at <code>/items/42.json</code>. Apart from the routing and http handling these items are stored somewhere (either BoltDB or Postgres using sqlx). Either way, I have now two <em>types</em> of items, as structs they look like this:</p>
<pre><code>type URLItem struct {
ID int
CreatedAt time.Time
URL string
}
type TextItem struct {
ID int
CreatedAt time.Time
Text string
}
</code></pre>
<p>I know, the difference is subtle, but I've kept this simple for the sake of the discussion.</p>
<p>I could create another struct named <code>Item</code> and put the <code>ID</code> and <code>CreatedAt</code> there and embed <code>Item</code> into both of these subtypes. I can work my way to storing these in Bolt or Postgres no problem, the thing is, what does my finder method look like? </p>
<pre><code>func FindItem(ID int) ?? {
// TODO
}
</code></pre>
<p>What does this return? It could be a <code>URLItem</code> or a <code>TextItem</code>. How would you make this work?? Using an interface here does not make it much better, as far as I can see. HELP!</p>
<hr/>**评论:**<br/><br/>climbinglepton: <pre><p>I think an interface would be the most elegant solution; clearly these two items are related. The problem is we'd have to know what you want to do with these structs and the like throughout your source code.</p>
<p>If you can find a way to make them "feel the same" as an interface I think it is preferable to returning an empty interface and type switching.</p></pre>john_84: <pre><p>I'd return an error.</p>
<p>Your probably making a external DB call right ? well look at how DB drivers return structs.</p>
<pre><code>func FindItem(ID int, result interface{})err
</code></pre>
<p>should be the signature of your method.</p>
<p>and you'd use it that way</p>
<pre><code>var item *URLItem
err := FindItem(someId,&item) // note the & before item
if err!=nil{
// do something about the error
}
// continue code
</code></pre></pre>climbinglepton: <pre><p>I think you have a bug there? "item" is already a pointer.</p>
<p>I'd go a little further:</p>
<pre><code>type SetTexter interface {
SetText(string)
}
type URLItem struct {
ID int
CreatedAt time.Time
URL string
}
func (u *URLItem) SetText(url string) {
u.URL = url
}
type TextItem struct {
ID int
CreatedAt time.Time
Text string
}
func (t *TextItem) SetText(txt string) {
t.Text = txt
}
func FindItem(ID int, result SetTexter) error {
// do stuff
result.SetText("my string")
// do stuff
return nil
}
</code></pre>
<p><a href="http://play.golang.org/p/J8IRGkxqvu" rel="nofollow">http://play.golang.org/p/J8IRGkxqvu</a></p></pre>hagemajr: <pre><p>It can return the empty interface{} which means it can return any type. You could then use the type switch to determine the type. </p>
<p><a href="https://github.com/golang/go/wiki/Switch#type-switch" rel="nofollow">https://github.com/golang/go/wiki/Switch#type-switch</a></p>
<p>Alternative:</p>
<pre><code>type ItemInterface interface {
GetItemValue() string
}
type Item struct {
ID int
CreatedAt time.Time
}
type URLItem struct {
Item
URL string
}
type TextItem struct {
Item
Text string
}
func (ui URLItem) GetItemValue(){
return ui.URL
}
func (ti TextItem) GetItemValue(){
return ti.Text
}
func FindItem(ID int) ItemInterface {
// TODO
}
</code></pre></pre>kelbyludwig: <pre><p>Interfaces would be the solution you are looking for. The concept of interfaces in Golang is similar to the concept of the interfaces in common object-oriented languages. Here are some references that helped me understand how Golang uses interfaces:</p>
<p><a href="https://gobyexample.com/interfaces" rel="nofollow">https://gobyexample.com/interfaces</a></p>
<p><a href="http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go" rel="nofollow">http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go</a></p>
<p><a href="http://research.swtch.com/interfaces" rel="nofollow">http://research.swtch.com/interfaces</a></p></pre>bkeroack: <pre><pre><code>func GetURLItems() []URLItem {}
func GetTextItems() []TextItem {}
resp := struct {
URLItems []URLItem `json:"url_items"`
TextItems []TextItem `json:"text_items"`
}{
URLItems: GetURLItems(),
TextItems: GetTextItems(),
}
jr, _ := json.Marshal(resp)
w.Write(jr)
</code></pre></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传