stack/context.go
func (c *Context) findRoots() {
	c.GOPATHs = map[string]string{}
	for _, f := range getFiles(c.Goroutines) {
		// TODO(maruel): Could a stack dump have mixed cases? I think it's
		// possible, need to confirm and handle.
		//log.Printf("  Analyzing %s", f)
		if c.GOROOT != "" && strings.HasPrefix(f, c.GOROOT+"/") {
			continue
		}
		if hasPathPrefix(f, c.GOPATHs) {
			continue
		}
		parts := splitPath(f)
		if c.GOROOT == "" {
			if r := rootedIn(c.localgoroot, parts); r != "" {
				c.GOROOT = r
				//log.Printf("Found GOROOT=%s", c.GOROOT)
				continue
			}
		}
		found := false
		for _, l := range c.localgopaths {
			if r := rootedIn(l, parts); r != "" {
				//log.Printf("Found GOPATH=%s", r)
				c.GOPATHs[r] = l
				found = true
				break
			}
		}
		if !found {
			// If the source is not found, just too bad.
			//log.Printf("Failed to find locally: %s / %s", f, goroot)
		}
	}
}
func (c *Context) findRoots() {
	c.GOPATHs = map[string]string{}
	for _, f := range getFiles(c.Goroutines) {
		// TODO(maruel): Could a stack dump have mixed cases? I think it's
		// possible, need to confirm and handle.
		//log.Printf("  Analyzing %s", f)
		if c.GOROOT != "" && strings.HasPrefix(f, c.GOROOT+"/") {
			continue
		}
		if hasPathPrefix(f, c.GOPATHs) {
			continue
		}
		parts := splitPath(f)
		if c.GOROOT == "" {
			if r := rootedIn(c.localgoroot, parts); r != "" {
				c.GOROOT = r
				//log.Printf("Found GOROOT=%s", c.GOROOT)
				continue
			}
		}
		found := false
		for _, l := range c.localgopaths {
			if r := rootedIn(l, parts); r != "" {
				//log.Printf("Found GOPATH=%s", r)
				c.GOPATHs[r] = l
				found = true
				break
			}
		}
		if !found {
			// If the source is not found, just too bad.
			//log.Printf("Failed to find locally: %s / %s", f, goroot)
		}
	}
}
// findRoots sets member GOROOT and GOPATHs.