One problem with running a Go program with the go run
command is that the directory of the built executable binary is not in the same directory where your "Main.go" file is located.
For instance, here's a program which prints the directory of the binary:
func main() {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
fmt.Println(dir)
}
This outputs on my laptop:
go run Main.go
/var/folders/2v/7n_r3hf539x6f6kf0m2zn5z40000gp/T/go-build855783190/b001/exe
You can build the binary first and have it placed in the same directory as your file.
go build -o myapp Main.go
Now we can print the actual directory where the binary lives:
./myapp
/Users/james/Desktop
If you need to hardcode the name of the file in your program and assume it lives in the same directory as your binary, you can now do this:
func main() {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
path := filepath.Join(dir, "shakespeare.txt")
b, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(err)
}
str := string(b)
text := strings.Split(str, " ")
fmt.Println(len(text))
}
Again, build then run the binary (I just added two words in my test file named "shakespeare.txt").
go build -o myapp Main.go
./myapp
2
Another option is to have your program accept the path of the file to read as an argument. This way it doesn't matter where your binary or your file lives since you pass that in directly.
func main() {
b, err := ioutil.ReadFile(os.Args[1])
if err != nil {
log.Fatal(err)
}
str := string(b)
text := strings.Split(str, " ")
fmt.Println(len(text))
}
You can run this with go run
or build it first as before:
go run Main.go ~/Desktop/shakespeare.txt
2