Is it possible to get the current root of package structure as a string in golang test?

golang project structure
golang package
golang example project
go modules
go install
go build
golang import
goroot

I am writing a utility function for my unit tests which is used by unit tests in multiple packages. This utility function must read a particular file (always the same file). Here are three solutions which do not work, to explain what I am looking for and why.

  1. Hardcode the absolute path. This fails because another user who is trying to test the project might have a different prefix on the absolute path.

  2. Hardcode a relative path from the path of the file which defines the utility function. This fails because packages which import and use this function are not necessarily at the same level of the file hierarchy as the file that defines the utility function, and relative paths are interpreted relative to the importer, not the imported.

  3. Pass in the relative path to the file from every caller relative to the caller's package. This actually works but seems to be very verbose because now every caller must be changed to pass one file.

I see a fourth solution, whereby I can hardcode a path in the utility function which is relative to the root directory of the top-level package. However, I have not been able to find a way to get the root directory in code, although I suspect there is one because imports can be resolved from the root.

Thus, how might I get the sought-after root directory?

I've looked over various Go documents but have so far failed to find a solution. I have also seen this question but the solution there is equivalent to #3 above.


You can also use my method without C:

package mypackage

import (
    "path/filepath"
    "runtime"
    "fmt"
)

var (
    _, b, _, _ = runtime.Caller(0)
    basepath   = filepath.Dir(b)
)

func PrintMyPath() {
    fmt.Println(basepath)
}

https://play.golang.org/p/ifVRIq7Tx0

How to reliably get the projects root in go?, So lets say I've a folder structure like this: I tested briefly how it interacts with go test -cover and it seems to work fine: func Executable() (string, error). Executable returns the path name for the executable that started the current process. package binpath import ( "os" "path" ) func getBinPath() string { e,  package main import "fmt" type rectangle struct { length float64 breadth float64 color string} func main { fmt.Println(rectangle{10.5, 25.10, "red"}) } The rectangle struct and its fields are not exported to other packages because identifiers are started with an lowercase letter. In Golang, identifiers are exported to other packages if the name


Returns the root of the application:

import (
    "path"
    "path/filepath"
    "runtime"
)  

func RootDir() string {
    _, b, _, _ := runtime.Caller(0)
    d := path.Join(path.Dir(b))
    return filepath.Dir(d)
}

Understanding Golang Packages – The New Stack, inside the simpleinterest folder. The following will be the directory structure of our application. The module root is not necessarily the directory of the current file. A better solution would be to search for all directories containing mod files and notify gopls about them, but we still haven't made a final decision on how we want to implement this.


Building on the answer by Oleksiy you can create a sub-package in your project called ./internal/projectpath/projectpath.go and paste in the following:

package projectpath

import (
    "path/filepath"
    "runtime"
)

var (
    _, b, _, _ = runtime.Caller(0)

    // Root folder of this project
    Root = filepath.Join(filepath.Dir(b), "../..")
)

Then you can use projectpath.Root in any other package to have the root folder of your project.

Learn to create and use Go packages, the command in a temporary directory then moves it to $GOPATH/bin . First you have to choose a name for your project and write it to go.mod file. This name belongs to root directory of the project. Each new package you create must be located inside it's own subdirectory and its name should match directory name. go.mod: module myprojectname or (preferred way, see @typical182's answer below for details)


Go directories:

// from Executable Directory
ex, _ := os.Executable()
fmt.Println("Executable DIR:", filepath.Dir(ex))

// Current working directory
dir, _ := os.Getwd()
fmt.Println("CWD:", dir)

// Relative on runtime DIR:
_, b, _, _ := runtime.Caller(0)
d1 := path.Join(path.Dir(b))
fmt.Println("Relative", d1)

What does go build build? (go build vs. go install), This document demonstrates the development of a simple Go package inside a A Go repository typically contains only one module, located at the root of the An import path is a string used to import a package. Commands like go install apply within the context of the module containing the current working directory. An import path is a string that uniquely identifies a package. A package's import path corresponds to its location inside a workspace or in a remote repository (explained below). The packages from the standard library are given short import paths such as "fmt" and "net/http". For your own packages, you must choose a base path that is unlikely


Yes, Finding package path is possible:

pathfind.go:

package main

/*
const char* GetMyPathFILE = __FILE__;
*/
import "C"
import "path/filepath"

var basepath = ""

//GetMyPath Returns the absolute directory of this(pathfind.go) file
func GetMyPath() string {
    if basepath == "" {
        g := C.GoString(C.GetMyPathFILE)
        basepath = filepath.Dir(g)
    }
    return basepath
}

All you have to do is copy this file to your project. Keep in mind this comes up with the path for the file, not the caller so you have to copy the function/file to every project you need the function in. Additionally if you put this in a file with other code be sure to respect CGO's import rules.

How to Write Go Code, Each directory listed in the Go path must have a prescribed structure: In Go 1.12 and earlier, it was possible to distribute packages in binary form without Unlike build constraints, this comment is only recognized in non-test Go source files. system GOROOT string // Go root GOPATH string // Go path // Dir is the caller's  As for test files, you can run individual test files by supplying the file name. go test foo/foo_test.go Lastly, use a base path and the path/filepath package to form file paths. Example: var ( basePath = "./public" templatePath = filepath.Join(basePath, "template") indexFile = filepath.Join(templatePath, "index.gtpl") )


build, This document demonstrates the development of a simple Go package and A workspace is a directory hierarchy with two directories at its root: command source main_test.go # test source stringutil/ reverse.go # package source The command go env GOPATH prints the effective current GOPATH ; it prints the default  How to Parse JSON in Golang (With Examples) October 18, 2017 (Updated on November 20, 2019) In this post, we will learn how to work with JSON in Go, in the simplest way possible. We will look at different types of data that we encounter in Go, from structured data like structs, arrays, and slices, to unstructured data like maps and empty


How to Write Go Code (with GOPATH), The build flags are shared by the build, clean, get, install, list, run, and test commands: type Package struct { Dir string // directory containing package sources system GOROOT string // Go root GOPATH string // Go path CgoEnabled bool If possible, init will guess the module path from import comments (see 'go help  String constants are easy to understand and provide a smaller space in which to explore the type issues of constants in Go. A string constant encloses some text between double quotes. (Go also has raw string literals, enclosed by backquotes ``, but for the purpose of this discussion they have all the same properties.) Here is a string constant:


go - The Go Programming Language, package hello func Hello() string { return "Hello, world." } Let's make the current directory the root of a module by using go mod init and In our example, go test resolved the new import rsc.io/quote to the module rsc.io/quote v1.5.2 . This gives module authors a clear rule about possible duplication of a  /test. Additional external test apps and test data. Feel free to structure the /test directory anyway you want. For bigger projects it makes sense to have a data subdirectory. For example, you can have /test/data or /test/testdata if you need Go to ignore what's in that directory. Note that Go will also ignore directories or files that begin