How to manage a REST API with allot of struct types

polaris · · 830 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi , I working on a rest API and i&#39;m using this todo code as reference [task.go(<a href="https://github.com/campoy/todo/blob/master/task/task.go" rel="nofollow">https://github.com/campoy/todo/blob/master/task/task.go</a>) In this example you create manger for each struct and then call the manager typed methods. I&#39;m creating a manager to each type but now i have 7 types and i dont want to create 7 managers.</p> <p>I thought about creating a wrapper struct that contains all the types and then i need to create only one manager .</p> <p>Can you think on a better way ?</p> <hr/>**评论:**<br/><br/>dwevlo: <pre><p>You can make <code>Task</code> an interface:</p> <pre><code>type Task interface { ID() int64 Title() string Done() bool } </code></pre> <p>Then make each of your 7 types implement the interface.</p> <p>Or you could add a <code>Type</code> field to the original struct:</p> <pre><code>type Task struct { ID int64 // Unique identifier Title string // Description Done bool // Is this task done? Type string } </code></pre> <p>Then use a switch on <code>Type</code> to do whatever you want. Maybe you could add a <code>Data</code> field if some types need extra information:</p> <pre><code>type Task struct { ID int64 // Unique identifier Title string // Description Done bool // Is this task done? Type string Data interface{} } </code></pre> <p>If you find a big switch too cumbersome you can also invert the control by using a map and having your handlers register:</p> <pre><code>type TaskHandler func(task Task) error var taskHandlers map[string]TaskHandler func init() { taskHandlers[&#34;my-custom-type&#34;] = func(task Task) error { return fmt.Errorf(&#34;do something here&#34;) } } </code></pre> <p>Then instead of the switch you just lookup the type in the map:</p> <pre><code>handler, ok := taskHandlers[task.Type] if ok { err = handler(task) } </code></pre></pre>jerf: <pre><p>I think your question is probably too vague to answer right now.</p> <p>You are aware of the context of that code, right? In a todo list manager, having a &#34;task manager&#34; be in some sense the &#34;primary&#34; interface to all the tasks makes sense. But this is a specific solution to the problems that arise in a task manager, which are weirder than they may first appear. (I have been vividly reminded of this lately by my shopping list app, which has some annoying bugs in it related to identity of &#34;tasks&#34; (things to buy) and how they are shared between users.) This &#34;TaskManager&#34; is not a generally-applicable pattern. Generally you start your REST interface in terms of manipulating the elements themselves.</p> <p>Anyway... to take my best shot at answering what I think your question is, jamming 7 things into a struct in the way I think you are suggesting is an antipattern. If there is a generic &#34;manager&#34; that makes sense for all your items, I&#39;d suggest declaring an interface that explains how the manager may &#34;manage&#34; them, then writing something like:</p> <pre><code>type Managed interface { Rename(string) // or whatever // and so on } type Manager struct { count int // or whatever bookkeeping you have managed []Managed } </code></pre> <p>It is also possible you want to put the interface on the array types themselves:</p> <pre><code>type ManagedList interface { Rename(int, string) } type Thing1 struct { name string // blah blah blah } type Things []Thing1 func (t *Things) Rename(idx int, name string) { t[idx].name = name } type Manager struct { managed ManagedList } </code></pre> <p>The minor tricky bit here is that if you have a Manager like this, you can easily JSON encode the data out, but you&#39;ll have a much harder time using the standard <code>encoding/json</code> package to read it in, as <code>encode/json</code> doesn&#39;t have a great story for reading things in to an interface value. (This is one place where <code>encoding/xml</code> has a legitimate advantage.) I think this can be solved if you can prepopulate the Manager with the right sort of &#34;managed&#34; object, but I have not checked it.</p> <p>It can also be an inconvenience that having just the &#34;Manager&#34; erases the actual type of the &#34;ManagedList&#34; thing; if you pass it somewhere the recipient of the Manager object won&#39;t automatically have a typed reference to what&#39;s in the ManagedList field. The solution is that you may find it advantageous to keep a reference to the thing you put under the Manager that has the correct type; if you&#39;re careful with what&#39;s a pointer you can still use the Manager to manipulate the typed reference with the Manager methods.</p> <p>If the preceding two paragraphs don&#39;t make sense right now, they probably will once you encounter the problems I&#39;m describing. :) Just keep in mind &#34;json decoding could be a bit tricky, come check this post&#34; and &#34;if I&#39;m typecasting the things in the Manager all the time, come check this post&#34;, and keep programming!</p></pre>

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

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