Database usage

xuanbao · · 524 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi</p> <p>I would like to ear your suggestions regarding the way i implement my db access. I surely think there is a better way to do this as my current solution is proving to be quite difficult to manage and audit this part of the code.</p> <p>So... here&#39;s how i currently implement the database access.</p> <p>In main.go package main</p> <pre><code>import &#34;models/user&#34; var user models.User func init(){ user.InitStatements() } </code></pre> <p>Then in models/user.go i have for each query something like this</p> <pre><code>package models const qSelectByID string = &#34;SELECT * FROM users WHERE id=$1&#34; type User struct { statements userStatements } type userStatements struct { selectByID *sqlx.Stmt } func (u *User) InitStatements() { var ( wg sync.WaitGroup // Selects selectByID *sqlx.Stmt ) wg.Add(1) go func() { defer wg.Done() var err error selectByID, err = db.Preparex(qSelectByID) if err != nil { log.WithFields(log.Fields{ &#34;query&#34;: qSelectByID, &#34;err&#34;: err, }).Error(&#34;Error preparing selectByID&#34;) } }() wg.Wait() u.statements.selectByID = selectByID } //Then i have my Model implementation bellow, where i use the statements above and the data and error management </code></pre> <p>Thanks!</p> <p>EDIT: fix wg.Add</p> <hr/>**评论:**<br/><br/>redditter15: <pre><p>Basically you are not applying the <a href="https://en.wikipedia.org/wiki/KISS_principle" rel="nofollow">Keep it Simple Stupid principle</a>.</p> <p>Get rid of the goroutine, it is not needed when you do not have at least 2 tasks at the same time.</p> <p>Also, don&#39;t use prepared statement if you are not going to do batch inserts. If I remember well, PostgreSQL won&#39;t even otimize the query (by using prepared statements) unless you have a given number of executions per second.</p></pre>metamatic: <pre><p>Also, <a href="https://www.reddit.com/r/golang/comments/4v5rs0/should_simple_db_statements_be_prepared_at/" rel="nofollow">check out this recent thread</a> -- the SQL statements you are carefully preparing might get invalidated by Go&#39;s management of the SQL connection pool. You shouldn&#39;t try to keep prepared statements around for the lifetime of a long-lived application.</p></pre>grutoc: <pre><p>To answer this issue, I went for:</p> <pre><code>type UserOP struct { Exec func(*User) error Close func() } func SelectUserByID(db sql.DB) (*UserOP, error) { stmt, err := db.Prepare(&#34;SELECT...&#34;) if err != nil { return nil, err } return &amp;UserOP{ Exec: func(u *User) error { res, err := stmt.Exec(u.ID) if err != nil { return err } return nil }, Close: func() { stmt.Close() }, }, nil } </code></pre></pre>toolateforTeddy: <pre><p>Well for one, why are you even luanching a goroutine here? This is single threaded code that you have shoved an extra thread into, and then continued to force it to be single threaded.</p> <p>Additionally, you Add(5) to the waitgroup, but only call .Done() once, so your .Wait() at the end will never return. You have deadlocked.</p></pre>norwat: <pre><p>Yeah the go routine part was only for performance issues kinda i just wanted the initStatements part to be faster so i tried to make as parallel as possible , it doesn&#39;t really need to be there </p> <p>The Add(5) its from the original code i forgot to edit that part out sorry</p> <p>Overall, is it a good solution?</p></pre>KenjiTakahashi: <pre><p>The way it is now, it won&#39;t be any faster, though. If anything, it will be slower, because it will have to take the time to spawn a goroutine.</p></pre>

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

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