Q: How to handle returns of different types?

polaris · · 452 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hey, I&#39;m new-ish to Go and I&#39;m still struggling with it not being OOP (that&#39;s what&#39;s been hammered into my brain since forever). I&#39;ve been struggling with modeling my stuff right, but I just can&#39;t make it work. </p> <p>Simply put, I&#39;m building a REST API. let&#39;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&#39;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&#39;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 &#34;feel the same&#34; as an interface I think it is preferable to returning an empty interface and type switching.</p></pre>john_84: <pre><p>I&#39;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&#39;d use it that way</p> <pre><code>var item *URLItem err := FindItem(someId,&amp;item) // note the &amp; 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? &#34;item&#34; is already a pointer.</p> <p>I&#39;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(&#34;my string&#34;) // 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:&#34;url_items&#34;` TextItems []TextItem `json:&#34;text_items&#34;` }{ URLItems: GetURLItems(), TextItems: GetTextItems(), } jr, _ := json.Marshal(resp) w.Write(jr) </code></pre></pre>

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

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