Learning Go, making a package, unsure how to initialise the package with a string from the code using the package?

blov · · 512 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m very very new to Golang and I&#39;m making a basic package that will do some mutations to a collection of strings when you call the methods.</p> <p>I&#39;m currently using ioutil.ReadFile in the package to read a text file, I then transform it into my struct that makes it easier to work with then I assign it to a global variable (var Data Words[]) - I do this in a method that gets invoked from my packages init() function.</p> <p>This works great for what I&#39;m doing but my issue is I want the user of the package to be able to specify the file they want to give the package when it imports.</p> <p>So I need a way to pass the filePath to the package on init().</p> <p>I&#39;m new to Golang so I&#39;m unsure how - can anyone help?</p> <p>Thanks</p> <hr/>**评论:**<br/><br/>ofpiyush: <pre><p>First of all, welcome to Go! Coming from a different language can make you feel a bit confused.</p> <p>Irrespective of the answer to the question, please do take <a href="https://tour.golang.org/welcome/1" rel="nofollow">the tour</a>. </p> <p>It usually helps to learn Go as a completely new language rather than trying to learn by differences from your current language.</p> <p>About the problem at hand,</p> <p>From what I can tell, you&#39;ve come from an interpreted language and you think of <code>init()</code> like a constructor of a class so to speak. It is and it isn&#39;t, depending on the way you look at it.</p> <p>The simplest solution is to have a method, other than <code>init()</code> or <code>main()</code> take the path and do exactly what you were doing with <code>init()</code>. I&#39;d suggest using something descriptive like <code>NewFromFile(path)</code></p> <p>The user of your program will have one extra method to call, but it is the shortest path to your success right now.</p> <p>After you have built your solution that way, the next step in go libraries is to understand that the community is <em>really</em> into interfaces. People will go as far as adding extra lines of code on their end to get a good and powerful abstraction.</p> <p>As <a href="/u/jimji" rel="nofollow">/u/jimji</a> said, you can generalise your lib to read from any <code>io.Reader</code> (files, tcp connections, body of a POST request, websockets etc) and perform your library&#39;s magic from a sister function to the one you are using right now <a href="https://golang.org/pkg/io/ioutil/#ReadAll" rel="nofollow"><code>ioutil.ReadAll</code></a></p> <p>The file based users of your lib can run <code>os.Open(filepath)</code> and pass the output <code>*os.File</code> which implements the <code>io.Reader</code> interface.</p> <p>With this powerful idea you can copy later part of your code to <code>func New(io.Reader)</code> and refactor <code>NewFromFile(path)</code> to use <code>os.Open</code> and the more general <code>New</code> function. You can even drop the <code>NewFromFile</code> function if you do not want to have two methods at various abstraction levels. </p> <p>People in general do not mind a couple of extra lines for this powerful abstraction in Go.</p> <p>Next steps from there would be to not have any Package level variables and returning the struct from the <code>New</code> function. Now your code is more testable and powerful, with just a couple of extra lines from the user. &lt;3</p></pre>bustyLaserCannon: <pre><p>Thanks so much! Really appreciate the help. I really do need to get around to finishing the tour - I just had an idea halfway through and decided to get building but I should take the time to finish it.</p> <p>Yeah I&#39;ve used languages like Java, C#, C++ and PHP in the past but I&#39;ve been a JavaScript &amp; Node developer for the past 2/3 years so I&#39;m not used to it yet.</p></pre>jiimji: <pre><p>just write a function that takes a io.Reader interface and returns whatever struct you need to return. </p></pre>weberc2: <pre><p>You can&#39;t pass arguments to init(). Your description is really hard to understand (maybe post a code snippet?), but what you&#39;re probably looking for is <a href="https://godoc.org/os#Args" rel="nofollow"><code>os.Args</code></a>. The first argument will be the program name, but the second argument will be whatever you pass into your program. So if you run your program <code>myprogram foo.csv</code>, then <code>os.Args[1]</code> will contain <code>&#34;foo.csv&#34;</code>. You can access this in your init function.</p></pre>bustyLaserCannon: <pre><p>I&#39;ll post a snippet when I&#39;m back off mobile but I&#39;m writing this package as a library to use in other golang apps. The idea being I make a call to my library like </p> <p>Mylib.GetValue(foo)</p> <p>But when mylib is imported I need it to read a file path provided from the program calling the lib. If this doesn&#39;t make sense I&#39;ll be able to post a code snippet in an hour or so.</p></pre>weberc2: <pre><p>Based on your description, you shouldn&#39;t rely on the <code>init()</code> method to do what you want, you should either create a package-level <code>Initialize(filepath string)</code> (which returns an error or panics), but I would suggest using struct instances instead of a global, and then creating a <code>NewFoo(filepath string) (Foo, error)</code> method. Instead of package-level methods, you will have methods on the <code>Foo</code> struct. This is more idiomatic and testable.</p> <p>EDIT: Here&#39;s an example.</p></pre>PsyWolf: <pre><p>So you can&#39;t have a constructor for your whole package which is sorta what you&#39;re asking for. I can&#39;t be sure without looking at the code, but it sounds like you should make all your functions into methods on a struct so that you can have a constructor.</p> <p>For example. Lets imagine you have a &#34;github.com/foobar/foo&#34; package. Inside it, make a Foo type with a constructor like</p> <pre><code>type Foo struct{ ... } func New(r io.reader) Foo { ... } </code></pre> <p>And then clients will use your library like</p> <pre><code>import ( &#34;os&#34; &#34;github.com/foobar/foo&#34; ) f, err := os.Open(&#34;foo.txt&#34;) check(err) myFoo := foo.New(f) myFoo.SomeFunc() </code></pre> <p>tl,dr; change your code to require struct initialisation instead of package initialisation. </p></pre>bustyLaserCannon: <pre><p>Thanks!</p></pre>mattn: <pre><p>FYI, you can write init() multiple. <a href="https://play.golang.org/p/ERlqLxKz8c" rel="nofollow">https://play.golang.org/p/ERlqLxKz8c</a></p></pre>

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

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