Search code examples
goio

Golang cannot write file into directory


Situation:

I'm trying to write a file into a directory, like shown as follows:

func (p *Page) Save() error {
    filepath := DerivePath(p.Title)
    fmt.Println(filepath)
    content, _ := json.MarshalIndent(p, "", "    ")
    err := ioutil.WriteFile(filepath, content, 0600)
    return err
}

Problem:

The following error occurs in line 5:

open data/Testpage.json: The system cannot find the path specified.

  • I already tried to create the file before writing with os.Create, but it doesn't work either.
  • Loading from the data directory works just fine. Only writing new files into the directory fails.

Additional information:

My project structure is as follows:

│   .gitignore
│   .project
│
├───bin
│       main.exe
│
├───data
│       Welcome.json
│
├───pkg
│   └───windows_amd64
│           page.a
│
├───src
│   ├───main
│   │       main.go
│   │
│   └───page
│           page.go
│           page_test.go
│
└───templates
        view.html

As mentioned above, reading data/Welcome.json works just fine (by using io/ioutils.ReadFile). The source is available on https://gitlab.com/thyaris/Wiki.

Executing D:\GitWorkspaces\Wiki\wiki>go test -v page writes the following output:

=== RUN   TestSave
data/Testpage.json
--- FAIL: TestSave (0.00s)
        page_test.go:15: open data/Testpage.json: The system cannot find the path specified.
        page_test.go:19: 'Testpage.json' was not created
=== RUN   TestLoadPage
--- FAIL: TestLoadPage (0.00s)
        page_test.go:26: Error while loading
        page_test.go:32: File content did not match
=== RUN   TestDelete
--- PASS: TestDelete (0.00s)
FAIL
exit status 1
FAIL    page    0.094s

Solution

  • Your problem here is that the test engine is not running your executable with the working directory you expect. Instead of using the working directory defined by your shell or IDE, it is setting it to the source directory of the code being tested. (I had this bite me too once, long ago :) I had almost forgotten about that...)

    The simple solution is to change DerivePath so that you can set the prefix externally, then change it to a the path you need at the beginning of your tests. There are other (possibly better?) solutions of course.