<p>I am creating db object in main function. Passing all handleFunc to a controller package and finally doing all db queries in model package. As i am creating db in main function, i need to pass it to controller package and then model function to do a complete call. Is this method right way to do? Should i use context library and save db on every call to fetch it or user global variable?</p>
<p>Which is right method to do this?</p>
<hr/>**评论:**<br/><br/>SerialMiller: <pre><p>Great question, I'm struggling with this myself. Currently I just create the connection in an init func and create a close func that I defer. In which I close the connection. </p>
<p>Not sure if this is the neatest way though.</p></pre>myth007: <pre><p>yes, even i am doing it, but not using in init function. I have created two modules, one is controller where i do my logic part and one model section where every DB thing will be done. Init function redirect url to controller function which calls model function for all db related tasks. Model runs sql queries and return output to controller which is processed by controller to send it back to user in response. Now as db is being created in init function, i need to pass it in each handler so that it can reach controller.
One issue is as it passes through controller so even controller has access to call DB query which i don't want to do.</p></pre>james-h: <pre><p>If your "model" package is the only package that is using it, define it as a global within that package. Otherwise, create a separate package for it.</p>
<p>Honestly, I would tend to go towards the second one. There's nothing wrong with having a package only for a database. And in my experience, having all of your models in a single package is not ideal. </p></pre>myth007: <pre><p>Can you please help elaborate why we should not have all models in single package? Just to explain, i want to have users model in user.go and same for others in model package.
As model package is only needed so planning to put it in that package only, so that others don't even try to use it.<br/>
It always help get other's point of view to make better decision.</p></pre>james-h: <pre><p>Certainly. It's not necessarily bad to have a package for your models, but once you start to have many different models, you might want to create some sub-packages.</p>
<p>I wrote a forum a few months ago and I didn't use a "model" package at all. I split the site into some of its logical components. For example, I had a "home" package, a "users" package and a "threads" package.</p>
<p>The "users" package acts as a model for the users. It has functions for inserting records, retrieving, updating...</p>
<p>I also had "userhandlers" package that had the HandlerFuncs in it. I found that this worked well.</p>
<p>If I had to do it again, I might create a "models" package and put the "users" package within it. Essentially, I think MVC is good, but keep in mind that MVC is all about separation, not grouping. You separate your controller from your model. And you should also separate your models where it makes sense.</p></pre>myth007: <pre><p>I completely agree with you in this. </p>
<blockquote>
<blockquote>
<p>And you should also separate your models where it makes sense.
Didn't think about this problem before, but agreed if i keep adding all model functions in one package, it might get messy. Just to make a visual difference, i am creating different files (one for each model like user, userlogin etc). Any suggestions here?</p>
</blockquote>
</blockquote></pre>james-h: <pre><p>Keeping the models in different files is certainly a start, but it can be limiting. For instance, what happens when one of your models gets large? Large files are cumbersome to deal with, you're often better breaking things up. So how do you name these files? How do you know which files belong to which models?</p>
<p>Giving each model a package provides intuitive separation and clean namespaces.</p></pre>myth007: <pre><p>For me one model is one table, each table has a file belonging to it, that way i can keep my logic of one table separate from other. This approach is picked from MVC framework of Php which i liked there. Will try to use separate package if things will go messy.</p></pre>virtuzz: <pre><p>On the other hand, when you want relations you'll face circular dependencies.</p>
<p>I just wrote a blog post about this: <a href="http://tonyhb.com/organising-database-models-in-go" rel="nofollow">http://tonyhb.com/organising-database-models-in-go</a></p></pre>cosiner_z: <pre><p>You can save <code>database.DB</code> as a global variable and init it in main function, then access it only in models or services. Commonly, controllers should not access the db.</p></pre>myth007: <pre><p>yes, agreed. I am also having same thinking. I read somewhere that global variables are not right way to do it. We should use context, not sure though. Any comments on that? Is it right to keep db variable global?</p></pre>cosiner_z: <pre><p>Define a global db in model package, and expose a initializer for it to be called in main function.</p>
<p>I think it's right tp use a single db instance in global scope, it's safety for concurrency. The context itself maintain another scope, is it necessary? Futher, if you store the db instance in a context, where you store the context variable, another context?</p></pre>myth007: <pre><p>agreed about content thing, in that case i need to store it in context for each call.
Storing it in model package is helpful, that way i can give a direct control to model package only. Will create different .go file in package for each type of model and everyone will use this db instance to run queries.</p>
<p>One more query, should i limit open connections of mysql to 1, as if i keep it more than one then there is a problem of two insert calls working on same data (as two open connection threads present on mysql db), i will keep that in mind and will never do this, but still your thoughts will help me get better understanding.</p></pre>blakecaldwell: <pre><p>I came to Go from Java, so I have the same instinct to layout my project like that, but back up a bit - do you need different packages? If you're going to have several services with different controllers, but using the same models or database library, then sure. But, in keeping with the spirit of being pragmatic, maybe just use one package. Thoughts?</p></pre>myth007: <pre><p>Ah, i also came from Java, worked on Php MVC framework too. I am more biased towards MVC framework as it divides responsibility between different modules. To achieve same thing here, i planned to create different package for each module, one reason to create package is to divide responsibility. I don't want any function in controller package to directly call any function from model without specifying model package while calling. This way i know when controller is calling model and no one can call a function of other package without specifying it. I am also doing it so that in future when someone else join me in my quest of writing good code, he don't mess up by writing any function at any place. Every function should go to its respective package.</p>
<p>My package struct is :
1. Main: Main.go
2. Controller: Which will handle all requests
3. Model: DB models.
4. Router: Router details
5. Config: Config variables which are used in webserver like port, mysql user name, password etc.
6. Log: Log file which will have all logs
7. Static: All HTML, CSS, JS and images goes here
8. Middleware: Using it for my specific middleware like my custom auth on each url hit.</p>
<p>Please hit me with your confusion, if any. Lets discuss in detail about different approaches to bring the best one out. :)</p></pre>cihangirsavas: <pre><p>From my experience(mine was a custom context for long lived shared connections, not x/net/context), i found passing context to (all?) functions is more clear, explicit and easy to manage. In the near feature you may need a custom logger, custom metrics collector, db, cache access struct etc, etc.. and you will be tempted to create all of them globally(because you already did it for db access!). this will create pain for testing e.g.: nil pointer panics, (might) needing to compile test binaries... when you create multiple workers/services, they will use the same models, but won't require a db access(lets say email sender worker), since you (not you myth007 :)) added it in <code>init</code>function, you have to connect to db(unnecessary resource consumption), and pass unnecessary arguments to your new worker(or needing another refactor), in some cases you will forget to close the db connection when you are done and will cause connection leak (because it is created in somewhere out of your sight) i can list many other but will stop for now :)</p>
<p>when to use net/context? when you need a unique identifier for your requests for debugging/tracing, when you want timeout support for any of your requests, when you want to pass request scoped data between your process/workers, you can use it safely</p>
<p><em>that leads a controversial question, why do we need to manage two things(custom context and net/context)?</em> because they help with different use cases.</p>
<p>tldr: your current methodology is the one i would chose over global variable. </p></pre>
What is right way to pass db instance to different functions in different packages?
polaris · · 1095 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传