Go cannot find file specified - go

I'm trying to make simple read settings from config file. Both files - config.json and Settings.go, are in the same folder. But I'm always getting "The system cannot find the file specified." What I'm doing wrong?
func GetDbConnectionString() string {
file, err := os.Open("config.json")
if err != nil {
log.Fatal(err)
}
decoder := json.NewDecoder(file)
settings := Settings{}
err1 := decoder.Decode(&settings)
if err1 != nil {
fmt.Println("error:", err1)
}
log.Print(&settings)
return fmt.Sprintf("%s:%s#/%s", settings.login, settings.password, settings.database)
}

Your settings.json is not in the same directory as your main.go. If you invoke either go run main.go, or go build . && ./app, the current path will be .../app/ which does not contain the settings.json file.
Try copying your settings.json file to the same directory as your app, local invocation will work (it will still fail if you run from a separate directory though).

Related

Can't read .env file without absolute path

When I try to read the .env file it does not work without using the absolute path.
func init() {
err := godotenv.Load(".env") //<--fails
//err := godotenv.Load("./.env") //<--fails
//err := godotenv.Load("/home/peter/Documents/tests/configuration/.env") //<--works
if err != nil {
panic(err)
}
Config = GetConfig()
}
I get panic: open .env: no such file or directory
But the file is there
$ ls -a
. .. config.go .env
Any clue?
A potential problem is that the directory you are running the executable from is different than the directory of which the .env file is located. Could you verify this?

What causes 'no such file or directory' after adding a test case and running go test?

The problem
After adding another test function to an existing test file running go test -v ./... fails due to several no such file or directory build errors after adding another test case. The error messages are seemingly unrelated to the changes, however.
The added test case can be found in the relevant code section at the bottom.
The error messages are:
open /tmp/go-build842273301/b118/vet.cfg: no such file or directory
open /tmp/go-build842273301/b155/vet.cfg: no such file or directory
# tornadowarnung.xyz/riotwatch/riot/static
vet: in tornadowarnung.xyz/riotwatch/riot/static, can't import facts for package "encoding/json": open $WORK/b036/vet.out: no such file or directory
# tornadowarnung.xyz/riotwatch/web/server/endpoint/static
vet: open $WORK/b121/vet.cfg: no such file or directory
open /tmp/go-build842273301/b115/vet.cfg: no such file or directory
open /tmp/go-build842273301/b001/vet.cfg: no such file or directory
# tornadowarnung.xyz/riotwatch/web/server
vet: open $WORK/b152/vet.cfg: no such file or directory
# tornadowarnung.xyz/riotwatch/web/server/endpoint/static
vet: open $WORK/b159/vet.cfg: no such file or directory
Because of that, some packages show their build failed:
FAIL tornadowarnung.xyz/riotwatch/riot/static [build failed]
FAIL tornadowarnung.xyz/riotwatch/web/server [build failed]
FAIL tornadowarnung.xyz/riotwatch/web/server/endpoint [build failed]
FAIL tornadowarnung.xyz/riotwatch/web/server/endpoint/static [build failed]
Relevant code
func TestLoader_ProfileIcon(t *testing.T) {
tempDir := os.TempDir()
l := Loader{
profileIconPath: tempDir,
}
defer os.RemoveAll(tempDir)
t.Run("returns expected content", func(t *testing.T) {
want := bytes.NewBufferString("image data")
fileName := "123456"
if err := createTestFile(t, tempDir, fileName, want); err != nil {
t.Fatal(err)
}
got, err := l.ProfileIcon(123456)
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
})
t.Run("does not panic on missing file", func(t *testing.T) {
res, err := l.ProfileIcon(-1)
if err == nil {
t.Errorf("Expected an error but got error %v and result %v", nil, res)
}
})
}
func createTestFile(t *testing.T, tempDir string, fileName string, content *bytes.Buffer) error {
t.Helper()
f, err := os.Create(path2.Join(tempDir, fmt.Sprintf("%v.png", fileName)))
if err != nil {
return err
}
_, err = f.Write(content.Bytes())
if err != nil {
return err
}
return nil
}
Reproducing the error is difficult
On my Ubuntu machine having go 1.15 installed the error only occurs sometimes when I'm cloning the repository again or when I'm cleaning the test cache.
When running the image used in the Gitlab job golang:alpine locally and running the same commands I cannot reproduce this error every time. Sometimes it occurs but most of the time it doesn't.
What I've tried
I have tried to switch between go versions 1.13, 1.14, and 1.15 but every version yields the same result.
Switching to any other images like golang:latest, golang:1.14 or golang:1.13 doesn't help either.
I've tried googling for the error that occurs but I haven't found any results that are relevant or contain any solution I haven't already tried.
Reverting said commit will make the tests pass again. I've also reverted the commit and slowly tried to introduce the changes again manually. This makes the problems occur again.
os.TempDir doesn't create a new temporary directory for you, it returns the system's temp dir. By calling os.RemoveAll on it, you're blowing away the entire thing, including some scratch files used by the build and test process.
I could validate the behaviour on a MacOS.
Seems like there is something wrong with the os.TempDir().
Your tests ran when I created the dir myself with os.Mkdir(...).
You should create an Issue in the Go repository.

How to use a config file while run compiled golang program

I build a go file using go build main.go. But this program is using a ini file, how do I use this file cause when I run ./main, I am getting this error:
2018/09/20 17:37:38 open config/config.ini: no such file or directory
2018/09/20 17:37:38 open config/config.ini: no such file or directory
panic: open config/config.ini: no such file or directory
goroutine 1 [running]:
log.Panic(0xc0000f7e98, 0x1, 0x1)
The code for using this file are:
func GetConfigFile() (*ini.File, error) {
f, err := ini.Load("config/config.ini")
if err != nil {
log.Println(err)
}
return f, err
}
It depends on where you run your program from. Read up on the concept of the current working directory, if you run your program from a console, the path is usually displayed at the start of the line. You use the relative path "config/config.ini" in your code which means that if you are currently in the directory /home/user then the file is expected to be at /home/user/config/config.ini.
You may want to either run your code from a different directory or use an absolute path in your code, e.g. /home/user/go/src/myapp/config/config.ini
Use absolute path like this :
func GetConfigFile() (*ini.File, error) {
f, err := ini.Load("/var/config/config.ini")
if err != nil {
log.Println(err)
}
return f, err
}

Scan for files in current directory only with ioutils ReadDir when imported through another file

I'm having an issue with ioutils.ReadDir, for some reason it's scanning for all files in the project root instead of in the current directory only.
./main.go
import (
"myfolder/myfile"
)
func main() {
myfile.MyFunction()
}
./myfolder/myfile.go
package myfile
func MyFunction() {
files, err := ioutil.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, f := range files {
fi, err := os.Stat(f.Name())
if err != nil {
log.Fatal(err)
return
}
switch mode := fi.Mode(); {
case mode.IsDir():
fmt.Printf("%#s is a folder\n", f.Name())
case mode.IsRegular():
fmt.Printf("%#s is a file\n", f.Name())
}
}
}
I'm not really sure why it is behaving like this, I'm new to Go. My guess is because it's being imported through main.go. How can I make it only search for folders and files in ./myfolder?
The current directory is not the directory of the source files, but rather the current directory of whoever executes the program.
If you're executing the program from a shell (be it bash or the Windows command line), the program inherits the current directory from your shell.
You must change the current directory with cd myfolder before executing the program or call os.Chdir("myfolder") in your Go source file. (os.Chdir doesn't affect your shell's current directory)
If you want to list a directory recursively, you must walk it. See filepath.Walk.

how to get the location of the current file in revel

I am using golang revel web framework and
I am trying to create a sqlite db in the current working directory.
model.go
func New(dbName string,table string) *Db {
_,filename,_,_ := runtime.Caller(1)
db , err := sql.Open("sqlite3",path.Join(path.Dir(filename),dbName))
if err != nil {
log.Fatal(err)
}
err = db.Ping()
if err != nil {
log.Panic(err)
}
database := &Db{Database:db}
_,err = db.Exec("create table %s" +
"( id integer primary key, " +
"name varchar(100),"+
"email varchar(100),"+
"branch varchar(100),"+
"help varchar(100)",)
if err != nil {
log.Fatal(err)
}
}
I have a test in place which just calls this function.
whenever i run the test using revel test or by going to the localhost:9000/#tests, the function Panics and the error message is
cannot open the database file.
The reason that is happening is because the filename returned by runtime.Caller(1) is /usr/local/go/src/runtime/asm_amd64.s for which the program has no permission.
if i directly write ./foo.db, even then the error shows.
I tried os.Getwd() which return empty string.
I also tried filepath.Abs(filepath.Dir(os.Args[0]))
but that returned /home/girish/GoProjects/bin/revel.d which is the revel binary.
So whats the best way to find the directory of the model.go?
It doesn't make sense to get the directory of the model.go file at runtime, because the compiled executable could be on a completely different filesystem.
You may want to get the directory of where the running executable was started from:
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
dir will be the folder where the program lives at runtime.

Resources