Package initialization order

polaris · · 664 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am trying to understand how package init functions are executed. <a href="https://golang.org/ref/spec#Program_initialization_and_execution" rel="nofollow">https://golang.org/ref/spec#Program_initialization_and_execution</a></p> <p>&#34;Package initialization—variable initialization and the invocation of init functions—happens in a single goroutine, sequentially, one package at a time. An init function may launch other goroutines, which can run concurrently with the initialization code. However, initialization always sequences the init functions: it will not invoke the next one until the previous one has returned.&#34;</p> <p>For instance, I have a config package and another package that uses config. In config. I have something like:</p> <pre><code>var Conf Config type Conf struct{ Directory string // more stuff } func init(){ // parse toml file into Conf variable } </code></pre> <p>In my other package I use the Conf variable from my config. Below code seems to work but is it guaranteed to be safe to have an init function here that uses Conf?</p> <pre><code>import &#34;/path/to/config&#34; var p string func init(){ p = config.Conf.Directory + &#34;thisfile.txt&#34; // more stuff } </code></pre> <hr/>**评论:**<br/><br/>nsd433: <pre><p>This code is fine. The language guarantees package A&#39;s init()s and globals are all called/initialized before any init()s in package B which imports A. From a little further down in the spec than your link:</p> <blockquote> <p>If a package has imports, the imported packages are initialized before initializing the package itself. If multiple packages import a package, the imported package will be initialized only once. The importing of packages, by construction, guarantees that there can be no cyclic initialization dependencies.</p> </blockquote> <p>The tricky part is the order in which init()s in the <em>same</em> package are executed. But that&#39;s not what you are asking about.</p></pre>froggert: <pre><p>The same section describes the order init functions are called with respect to imports:</p> <blockquote> <p>If a package has imports, the imported packages are initialized before initializing the package itself. If multiple packages import a package, the imported package will be initialized only once. The importing of packages, by construction, guarantees that there can be no cyclic initialization dependencies.</p> </blockquote></pre>natefinch: <pre><p>Don&#39;t rely on something being done in one init function before code from another init function runs. Write them like they could happen in any order, if at all possible.</p></pre>natefinch: <pre><p>Ideally, simply don&#39;t have an init function, and pass the data into the package when it is used.</p></pre>JHunz: <pre><p>An imported package&#39;s init function is guaranteed by the language spec to be run before the init function of the package importing it. This is nonsense.</p></pre>natefinch: <pre><p>Sorry, you&#39;re right, I misunderstood the question. It is safe.</p> <p>However, I still think that it&#39;s generally best to avoid anything complicated in init functions, since they can be very hard to test. Parsing a config file is definitely in that vein. much better to have</p> <pre><code>func ParseConfig(r io.Reader) Config {} </code></pre> <p>and then pass that config value into another function that gives you a value to work with. Way easier to test.</p></pre>fortytw2: <pre><p>Not just easier to test, but far easier to read and follow the flow of data throughout the program </p></pre>

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

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