<p>I'm very very new to Golang and I'm making a basic package that will do some mutations to a collection of strings when you call the methods.</p>
<p>I'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'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'm new to Golang so I'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'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'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'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'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. <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've used languages like Java, C#, C++ and PHP in the past but I've been a JavaScript & Node developer for the past 2/3 years so I'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't pass arguments to init(). Your description is really hard to understand (maybe post a code snippet?), but what you'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>"foo.csv"</code>. You can access this in your init function.</p></pre>bustyLaserCannon: <pre><p>I'll post a snippet when I'm back off mobile but I'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't make sense I'll be able to post a code snippet in an hour or so.</p></pre>weberc2: <pre><p>Based on your description, you shouldn'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's an example.</p></pre>PsyWolf: <pre><p>So you can't have a constructor for your whole package which is sorta what you're asking for. I can'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 "github.com/foobar/foo" 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 (
"os"
"github.com/foobar/foo"
)
f, err := os.Open("foo.txt")
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>
Learning Go, making a package, unsure how to initialise the package with a string from the code using the package?
blov · · 512 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传