<p><a href="https://gist.github.com/anonymous/b6babbec57fc0d626fad">Here</a> are two functions that do the same thing, but on two different types. This seems overly repetitive, and I'd like to refactor it into a single method, but am unsure of the idiomatic Go way. Would it be to use interface{} and cast, just leave it as two methods, or something else? </p>
<hr/>**评论:**<br/><br/>skidooer: <pre><p>Without knowing more about your application, here is one approach:</p>
<pre><code>// TODO update Post and Page to conform to the interface.
type sanitizer interface {
GetRawContent() []byte
SetSafeContent(string)
}
func fetch(c appengine.Context, q *datastore.Query, items []sanitizer) {
if _, err := q.GetAll(c, &items); err != nil {
// TODO this should go to the log instead
fmt.Println("FAILURE!!!!!!")
}
policy := bluemonday.UCGPolicy()
for _, p := range x {
parsed := blackfriday.MardownCommon(p.GetRawContent())
html := policy.SanitizeBytes(parsed)
p.SetSafeContent(template.HTML(html))
}
}
</code></pre></pre>bitcycle: <pre><ol>
<li><p>The return type indicates that there is at least one code path where an error would be returned. I would expect them both to return if <code>GetAll</code> failed, but neither do. </p></li>
<li><p>Use an interface to provide <code>GetRawContent() []byte</code> and <code>SetSafeContent(string)</code> just like in <a href="/u/skidooer">/u/skidooer</a> 's answer. Note, he updated the method name to use a setter method instead of just <code>SafeContent</code> -- which only works if you own the definition in your app for <code>Post</code> and <code>Page</code>.</p></li>
<li><p>Add at least a comment explaining what Bluemonday UCG Policies are -- because obscure acronyms from third party libs suck most of the time, or refer to the Bluemonday comment in the <code>policy.go</code> source <a href="https://github.com/microcosm-cc/bluemonday/blob/1f0bc57c5484fb9207c08d5ed7475feaea9e3002/policy.go#L38">here</a>. In addition, you might add a <code>SECURITY.md</code> file to your project outlining how using Bluemonday (and potentially other security-minded libraries) will ensure the safety and security of the application.</p></li>
</ol></pre>kromem: <pre><p>You can very easily take control of an externally defined type by embedding it into a locally defined type and overriding/adding the desired methods. </p></pre>bitcycle: <pre><p>Examples?</p></pre>jshen: <pre><p>Thanks for the feedback. Regarding point 1, his is incomplete code I am actively working on. There will be a code path where an error is returned, but I should have cleaned it up before posting it.</p></pre>legec: <pre><p>Is there any point in caching the SafeContent right here ?</p>
<pre><code>type content string
func (ctnt content) Safe() template.HTML {
parsed_content := blackfriday.MarkdownCommon([]byte(ctnt))
html := bluemonday.UGCPolicy().SanitizeBytes(parsed_content)
return template.HTML(html)
}
type Post struct {
ID int
Content content
}
type Page struct {
ID int
Content content
}
// post.Content.Safe()
// page.Content.Safe()
</code></pre>
<p>You would have to check how this interacts with datastore.</p></pre>gdey: <pre><p>Yeah, I would pull it out and define an interface for it.
<a href="http://play.golang.org/p/7wm1l8ZuMl" rel="nofollow">http://play.golang.org/p/7wm1l8ZuMl</a></p>
<p>I would not pull out the the GetAll calls.</p></pre>jshen: <pre><p>Yeah, that works. I guess that still feels repetitive to me coming from dynamic languages since I'll end up making a fetchXXX method for every new type. I'd just have a single generic fetch method in ruby, or in a language with generics. </p></pre>tagesticket: <pre><p>You could do something similar to the sort package. Here's a sample: <a href="http://play.golang.org/p/dNsxw7KasV" rel="nofollow">http://play.golang.org/p/dNsxw7KasV</a></p></pre>earthboundkid: <pre><p>The core of the two for-loops are the same. That should be pulled out into its own function. </p></pre>G0T0: <pre><p>I imagine all of:</p>
<pre><code>_, err := q.GetAll(c, &post)
if err != nil {
fmt.Println("FAILURE!!!!!!")
}
for i, p := range posts {
parsed_content := blackfriday.MarkdownCommon([]byte(p.Content))
html := bluemonday.UGCPolicy().SanitizeBytes(parsed_content)
p.SafeContent = template.HTML(html)
posts[i] = p
}
</code></pre>
<p>can be pulled out.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传