New to Go/Golang and am trying to understand its package/dependency management system a little better.
I cloned this simple web service repo off GitHub and tried running it with go run main.go. In that main.go file:
package main
import (
"log"
"net/http"
"strconv"
"github.com/wpferg/services/httpHandlers"
"github.com/wpferg/services/storage"
"github.com/wpferg/services/structs"
)
const PORT = 8080
var messageId = 0
func createMessage(message string, sender string) structs.Message {
messageId++
return structs.Message{
ID: messageId,
Sender: sender,
Message: message,
}
}
func main() {
log.Println("Creating dummy messages")
storage.Add(createMessage("Testing", "1234"))
storage.Add(createMessage("Testing Again", "5678"))
storage.Add(createMessage("Testing A Third Time", "9012"))
log.Println("Attempting to start HTTP Server.")
http.HandleFunc("/", httpHandlers.HandleRequest)
var err = http.ListenAndServe(":"+strconv.Itoa(PORT), nil)
if err != nil {
log.Panicln("Server failed starting. Error: %s", err)
}
}
When I run this (run go main.go) I get:
main.go:8:2: cannot find package "github.com/wpferg/services/httpHandlers" in any of:
/usr/local/go/src/github.com/wpferg/services/httpHandlers (from $GOROOT)
/Users/myuser/go/src/github.com/wpferg/services/httpHandlers (from $GOPATH)
main.go:9:2: cannot find package "github.com/wpferg/services/storage" in any of:
/usr/local/go/src/github.com/wpferg/services/storage (from $GOROOT)
/Users/myuser/go/src/github.com/wpferg/services/storage (from $GOPATH)
main.go:10:2: cannot find package "github.com/wpferg/services/structs" in any of:
/usr/local/go/src/github.com/wpferg/services/structs (from $GOROOT)
/Users/myuser/go/src/github.com/wpferg/services/structs (from $GOPATH)
So it seems Go supports a way of "fetching" other packages from GitHub via HTTP but for some reason when I run it locally, its expecting the packages to be local.
What can I do to fix this so that the other packages are resolved? Why is Go looking for them locally instead of fetching them via the URL?
Problem is that this repo is from pre go modules era and doesn't use any dependency management system. Easiest way to fix it is to try to initialize it as module(if you use go < 1.14 set environment variable GO111MODULE=on):
go mod init github.com/wpferg/services
And then run:
go run main.go
it will resolve it's dependencies automatically and try to start the program.
P.S. But, regarding that it's an older code and it's unclear with what golang version(and packages versions) it was written it's likely that it will not work or, in some way, will be broken.
In my case, imports worked for a long time, then suddenly didn't.
I fixed it by running go mod tidy in the console.
Related
I'm using the following Go module to build an application:
github.com/martinlindhe/unit
Right now, the Go code is very simple; I'm just trying to get the environment set up for the real work:
import(
"fmt"
"unit"
)
foo := unit.FromFahrenheit(100)
fmt.Println("100 fahrenheit in celsius = ", foo.Celsius())
In go.mod:
go 1.17
require github.com/martinlindhe/unit v0.0.0-20210313160520-19b60e03648d
Executing either go build or go get results in:
package unit is not in GOROOT (/usr/local/Cellar/go/1.17/libexec/src/unit)
Running go mod download executes without error. The go.sum file seems to be correct, all the necessary dependencies exist.
The environment is the latest version of VS Code, Go installed via homebrew on MacOS Big Sur 11.5.2
There must be something obvious I'm missing. I've not had this problem with other apps I've written.
The import path is not right. Playground.
package main
import (
"fmt"
"github.com/martinlindhe/unit"
)
func main() {
foo := unit.FromFahrenheit(100)
fmt.Println("100 fahrenheit in celsius = ", foo.Celsius())
}
I have an issue with importing a local package in my go project. It seems that while I'm working locally I have to import with the full path: "github.com/username/myproject/mypackage". But when I push to heroku I get an error about not being able to find that package. If I change the import to "myproject/mypackage", it works on heroku, but no longer works locally.
The two solutions I've seen while researching seem like workarounds:
Put my local packages into vendor/. My understanding is that the vendor directory is intended for third party libraries, so I'd rather not misuse that.
Move myproject/ to be directly in src/. All the golang resources seem to stress that the file structure is very important and that I should have a github.com folder. I'm not clear on why the file structure is important, so this is the solution I'm going with right now, but I can't help but think I'm doing something wrong.
Has anyone else encountered this issue? I've included my file structure, .go files, and Godeps.json below for clarity.
My file structure:
$GOPATH
└───bin
└───pkg
└───src
└───github.com
└───username
└───myproject
│ main.go
└───Godeps
│ │ Godeps.json
└───mypackage
│ mypackage.go
mypackage.go
package mypackage
import (
"fmt"
)
func PrintHelloWorld() {
fmt.Println("Hello, world!")
}
main.go:
package main
import (
"fmt"
"github.com/username/myproject/mypackage" // import causing problems in heroku
"log"
"net/http"
"log"
)
func sayHelloWorld(w http.ResponseWriter, r *http.Request) {
mypackage.PrintHelloWorld()
fmt.Fprintf(w, "Hello world!")
}
func main() {
http.HandleFunc("/", sayHelloWorld)
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Godeps.json:
{
"ImportPath": "myproject",
"GoVersion": "go1.10",
"GodepVersion": "v80",
"Deps": []
}
Error when pushing to heroku:
-----> Go app detected
-----> Checking Godeps/Godeps.json file.
-----> Using go1.10
!! Installing package '.' (default)
!!
-----> Running: go install -v -tags heroku .
main.go:6:2: cannot find package "github.com/username/myproject/mypackage" in any of:
/tmp/tmp.xY81RbKUze/.go/src/myproject/vendor/github.com/username/myproject/mypackage (vendor tree)
/app/tmp/cache/go1.10/go/src/github.com/username/myproject/mypackage (from $GOROOT)
/tmp/tmp.xY81RbKUze/.go/src/github.com/username/myproject/mypackage (from $GOPATH)
! Push rejected, failed to compile Go app.
I have follow two simple go files
main.go
package main
import "fmt"
import "go-package/math"
func main() {
xs := []float64{1, 2, 3, 4}
avg := math.Average(xs)
fmt.Println(avg)
}
mymath.go
package math
func Average(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total / float64(len(xs))
}
The file and directory structure is:
$GOPATH
src
go-package
math
mymath.go
main.go
When I navigate to $GOPATH/src/go-package, and open the terminal and run the command: go run main.go, the result is printed out.
Then, I navigate to $GOPATH/src/go-package/math, and run the command go install, and the package successfully installed at $GOPATH\pkg\windows_amd64\go-package\math.a
Then I navigate back to $GOPATH/src/go-package, and remove the math directoy,
I rerun the command go run main.go, error occurs:
main.go:4:8: cannot find package "go-package/math" in any of:
D:\softwareInstalled\Go\src\go-package\math (from $GOROOT)
D:\softwareInstalled\Go\GoPath\src\go-package\math (from $GOPATH)
I have put the math package at $GOPATH\pkg\windows_amd64\go-package\math.a
I wonder why Go doesn't pick up the package from this directory.
And how can I use math.a?Where should I place it?
Golang uses the source files of your imported packages. So when you wanna use the package go-package/math inside your main.go, you should not delete the source files from src/go-package/math. Leave them inside your project and everything's good.
Besides, go get also loads source files into your $GOPATH/src folder. Hope this helps.
I want to step through my program using Godebug. However because I'm using net/http I get errors such as:
/home/heath/go/src/net/http/h2_bundle.go:45:2: could not import golang_org/x/net/http2/hpack (cannot find package "golang_org/x/net/http2/hpack" in any of:
/home/heath/go/src/golang_org/x/net/http2/hpack (from $GOROOT)
/x/net/http2/hpack does exist in my GOPATH but in ~heath/go/src/golang.org ... not golang_org (not sure what's happening there)
I have read that this error occurs because godebug doesn't support http2 yet (can't find source).
I have tried to disable http2server and http2client by setting the GODEBUG env both in init() and on the command line. I have also confirmed that these settings are being set by doing a fmt.Println("GODEBUG", os.Getenv("GODEBUG"). As per instructions located here
GODEBUG=http2client=0 # disable HTTP/2 client support
GODEBUG=http2server=0 # disable HTTP/2 server support
My simple code example to replicate the error is:
package main
import "fmt"
import "net/http"
import "os"
func init() {
os.Setenv("GODEBUG", "http2server=0,http2client=0")
}
func main() {
fmt.Println("GODEBUG", os.Getenv("GODEBUG"))
_ = "breakpoint"
fmt.Println("Hello, World!")
http.ListenAndServe(":8080", nil)
}
godebug run example.go
I am running Go version:
go version go1.7 linux/amd64
This is probably not the correct way to do things. But I copied the http2 package from my vendor directory under $GOROOT/src/vendor to the src directory under my $GOPATH/src.
If anyone has any further input on the correct way to reference vendor directories please add your thoughts. Just putting my workaround here in case someone else comes across the same issue.
Edit: Actually a 'nicer' way to do things was to do an ln -s ..src/vender/github_org to ../src/github_org
I want to run a go file, main package imported a local package which imported a github package. and get an error (missing .a file)
ENV:
$GOROOT=/usr/local/go
$GOPATH=/gopath
go version 1.6.3 (same problem in 1.6.2)
I tried to run a go file like this:
/gopath/src/myproj/main/app.go
package main
import (
"../http/server"
)
func main() {
server.Run()
}
/gopath/src/myproj/http/server/route.go
package server
import (
"github.com/gorilla/mux"
"net/http"
)
func Run(){
router := mux.NewRouter()
router.HandleFunc("/", handler)
http.Handle("/", router)
http.ListenAndServe("9090", nil)
}
func handler(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Hello"))
}
then,I run go get github.com/gorilla/mux and I can see there are files
/gopath/pkg/linux_amd64/github.com/gorilla/mux (there are context.a and mux.a)
/gopath/src/github.com/gorilla/mux
/gopath/src/github.com/gorilla/context
Yes, src file and pkg file(.a) has downloaded form github,
BUT , I run "go run main/app.go" , get
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: cannot open file /usr/local/go/pkg/linux_amd64/github.com/gorilla/mux.a: open /usr/local/go/pkg/linux_amd64/github.com/gorilla/mux.a: no such file or directory
compiler does not find file in GOPATH, but GOROOT
if I copy $GOPATH/pkg files to $GOROOT/pkg was good.
And, if I import github.com/gorilla/mux in main package directly was fine too.
As JimB said don't use relative paths for imports
if you change "../http/server" to myproj/http/server it shouldn't have the linking problems anymore