How to use a config file while run compiled golang program - go

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
}

Related

check file existence without using os.Stat after locking the path

When I lock a file path with flock then check the file existence it return no error even though there is no file in that path. The code follows:
filePath := filepath.Join(r.path, fmt.Sprintf("%s_event.json", eventId))
fileLock := flock.New(filePath)
fileLock.Lock()
defer fileLock.Close()
_, err = os.Stat(filePath)
if err != nil {
if os.IsNotExist(errs) {
return event, EventNotFound{}
}
return
}
But when at first check the Stat then lock the file it works. I need to check it before that. Every idea is welcome!

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.

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.

Go cannot find file specified

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).

How to specify the file location for `template.ParseFiles` in Go Language?

After I watched this video, I try it myself. However, I get the panic error panic: open templates/index.html: The system cannot find the path specified. The Complete erroe message is like the following.
Hello, Go Web Development 1.3
panic: open templates/index.html: The system cannot find the path specified.
goroutine 1 [running]:
panic(0x789260, 0xc082054e40)
F:/Go/src/runtime/panic.go:481 +0x3f4
html/template.Must(0x0, 0xe34538, 0xc082054e40, 0x0)
F:/Go/src/html/template/template.go:340 +0x52
main.main()
E:/Users/User/Desktop/codespace/go_workspace/src/go-for-web-dev/src/1.3_UsingTemplate.go:11 +0x20d
I have tried different string like "templates/index.html", "index.html", "./template/index.html"... Also, I try to copy the entire template folder into pkg, bin...But I get the same error message.
The following is the go program (1.3_UsingTemplate.go).
package src
import (
"fmt"
"net/http"
"html/template"
)
func main() {
fmt.Println("Hello, Go Web Development 1.3")
templates := template.Must(template.ParseFiles("templates/index.html")) //This line should have some problem
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if err := templates.ExecuteTemplate(w, "index.html", nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
fmt.Println(http.ListenAndServe(":8080",nil))
}
File Structure
Update
To solve this problem, I need to first change the current working directory to the folder containing the *.go file. Then, execute go run {filename.go}. In GoClipse, is there any setting can be set to the Run Configurations for automatically changing the current working directory to the folder containing the *.go file?
os.Getwd() can be used to return the root working directory of your project and then concatenate with the inner path of your template file:
// Working Directory
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
// Template
tpl, err := template.ParseFiles(wd + "/templates/index.html")
You specified a path relative to the current working directory. This directory may not have any relationship with the directory containing the source code.
Change directory to E:/Users/User/Desktop/codespace/go_workspace/src/go-for-web-dev/src to run your program. The path to the template is relative to this directory.

Resources