Creating a project with Go modules - go

I'm trying to understand Go modules and create a simple hello world program. Go version: 1.16.2
/project1
/project1/main.go
/project1/helpers/helpers.go
helpers.go will contain some utility method like:
package ???
import "fmt"
func DoSomething() {
fmt.Println("Doing something in helpers.go")
}
main.go will use methods from helpers.go like this:
package main
import "??"
func main() {
helpers.DoSomething()
}
VSCode is not allowing me to do this and has a red underline on helpers.
What am I missing here? How can I achieve this?
Edit 1: Adding go.mod and package names:
So I ran go mod init helpers in /helpers folder and came out with this:
/project1/helpers/helpers.go
/project1/helpers/go.mod
go.mod
module helpers
go 1.16
My main.go now looks like this:
package main
import (
"fmt"
"helpers"
)
func main() {
fmt.Println("blah")
helpers.DoHelperMethod()
}

Your project should have only one go.mod file and it should be in the root of the project. You can cd into the project's directory and do go mod init <module_name> where <module_name> in your case can be project1.
For example, once you've initialized the module, your project should look something like the following:
/project1/helpers/helpers.go
/project1/main.go
/project1/go.mod
go.mod
module project1
go 1.16
main.go
package main
import "project1/helpers"
func main() { helpers.DoHelperMethod() }
helpers/helpers.go
package helpers
func DoHelperMethod() {
// ...
}

Related

Go: import package from the same module in the same local directory

I want to create new package mycompany that will be published on Github at github.com/mycompany/mycompany-go (something similar to stripe-go or chargebee-go for example).
So I have created a folder ~/Desktop/mycompany-go on my MacOS. Then inside that folder I run go mod init github.com/mycompany/mycompany-go.
I have only these files in that local folder:
// go.mod
module github.com/mycompany/mycompany-go
go 1.19
// something.go
package mycompany
type Something struct {
Title string
}
// main.go
package main
import (
"github.com/mycompany/mycompany-go/mycompany"
)
func main() {
s := mycompany.Something {
Title: "Example",
}
}
However I get this error:
$ go run main.go
main.go:4:3: no required module provides package github.com/mycompany/mycompany-go/mycompany; to add it:
go get github.com/mycompany/mycompany-go/mycompany
I think that this is a wrong suggestion, because I need to use the local version, in the local folder, not get a remote version.
Basically I need to import a local package, from the same folder, from the same module.
What should I do? What's wrong with the above code?
You can't mix multiple packages in the same folder.
If you create a folder mycompany and put something.go inside it, that should fix the problem
The Go tool assumes one package per directory. Declare the package as main in something.go.
-- main.go --
package main
import "fmt"
func main() {
s := Something{
Title: "Example",
}
fmt.Println(s)
}
-- go.mod --
module github.com/mycompany/mycompany-go
go 1.19
-- something.go --
package main
type Something struct {
Title string
}
Runnable example: https://go.dev/play/p/kGBd5etzemK

Go run/build cannot find source files

I am trying to run a simple hello world style program that imports a print function from a separate custom package but Go is unable to find it despite teh correct $GOPATH etc being set.
What is missing that will make teh file be picked up?
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ echo $GOPATH
/home/etherk1ll/Development/GoWorkSpace/
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ pwd
/home/etherk1ll/Development/GoWorkSpace/src/sonarparser
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ ls
jsonparser.go main.go
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ go run main.go
main.go:5:2: cannot find package "sonarparser/jsonparser" in any of:
/usr/local/go/src/sonarparser/jsonparser (from $GOROOT)
/home/etherk1ll/Development/GoWorkSpace/src/sonarparser/jsonparser (from $GOPATH)
main.go
package main
import (
"fmt"
"jsonparser"
)
func main() {
fmt.Println("Hello world 1")
fmt.Println(jsonparser.HelloTwo)
}
jsonparser.go
package jsonparser
import "fmt"
func HelloTwo() {
fmt.Println("Hello world 2")
}
Because jsonparser.go and main.go are in the same package, Go requires those files to have the same package name. And because you defined the main function for the execution, the package must be "main".
Step 1: So you should rename jsonparser.go's package to main.
// jsonparser.go
package main
import "fmt"
func HelloTwo() {
fmt.Println("Hello world 2")
}
Step 2: You need to update main.go file to correct the import path:
// main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello world 1")
HelloTwo()
}
Step 3: Then you run the following command (you must include all necessary files in the command)
go run main.go jsonparser.go

How to include the package in local directory in to the main.go

I am using go version go1.11.2 windows/amd64 in windows 10
i have folder in desktop with name "GoPro" which has
one file - main.go
one folder - Modules
The "Modules" folder contains
one file - Modules.go
Folder Structure
Desktop
|------->GoPro
|----->main.go
|----->Models
|---->Models.go
main.go
// desktop/GoPro/main.go
package main
import (
"./Models"
)
func main() {
Models.Printhello()
}
Models.go
// desktop/GoPro/Models
package Models
import "fmt"
func Printhello() {
fmt.Println("Hello")
}
If try to run the main.go , I am getting the below error , Go recongise the package but it saying undefined.
go run main.go
command-line-arguments
.\main.go:8:2: undefined: Models
The folder is not in GOPATH. I am just trying to import the package with in sub folder of main.go
You can either set up $GOPATH and place your library in a path relative to $GOPATH, or use modules.
For modules, you can do something like:
$ tree
.
├── go.mod
├── main.go
└── mylib
└── mylib.go
Contents of files:
$ cat go.mod
module myproject.com
====
$ cat main.go
package main
import "myproject.com/mylib"
func main() {
mylib.Say()
}
====
$ cat mylib/mylib.go
package mylib
import "fmt"
func Say() {
fmt.Println("Hello from mylib")
}
P.S. use lowercase to name packages/modules

Structuring local imports without GitHub in Golang

I'm building a simple app and after reading the doc on structuring go applications, I'm still confused.
I want this structure:
practice
models (packaged as models)
a
b
routers (packaged as routers)
a
b
app.go
Inside of app.go, I have the following:
package main
import (
"net/http"
// I have tried the following:
"practice/models/a"
"practice/models/b"
"practice/models"
"$GOPATH/practice/models/a"
"$GOPATH/practice/models/b"
"$GOPATH/practice/models"
...
)
func main() {
http.HandleFunc("/a", AHandler)
http.HandleFunc("/b", BHandler)
http.ListenAndServe(":8080", nil)
}
The A and B models look like this:
package models
import "net/http"
func AHandler(w http.ResponseWriter, r *http.Request) {
// code
}
Two questions:
What in the world is the right way to import these files? Do I really have to push them to github in order to be able to reference them? I understand the $GOPATH is the namespace for the entire go workspace on a local machine. My $GOPATH is set to include this directory.
Do I need to define a main method inside of these files? Can I just export a single function and have that be the handling function?
I have consulted the docs
See How to Write Go Code.
Use this directory structure:
- practice
- go.mod
- app.go
- models
- a.go
- b.go
- routers
- a.go
- b.go
where go.mod is created with the command go mod init practice where practice is the module path.
Import the packages as follows:
import (
"practice/routers"
"practice/models"
...
)
Use the imported packages like this:
func main() {
http.HandleFunc("/a", models.AHandler)
http.HandleFunc("/b", models.BHandler)
http.ListenAndServe(":8080", nil)
}
You do not need to push to github.com, even if you use github.com in the module path.
The main function in the main package is the entry point for the application. Do not define main functions in packages other than main.
What follows is the original answer based on GOPATH workspaces:
See How to Write Go Code.
Create your directory structure under $GOPATH/src.
$GOPATH
src
practice
models
routers
Import the packages as follows:
import (
"practice/routers"
"practice/models"
...
)
Use the imported packages like this:
func main() {
http.HandleFunc("/a", models.AHandler)
http.HandleFunc("/b", models.BHandler)
http.ListenAndServe(":8080", nil)
}
You do not need to push to github.com, even if you use 'github.com' in the file path.
The main function in the main package is the entry point for the application. Do not define main functions in packages other than main.
I think the other answer is out of date, you don't need to use GOPATH anymore.
Run:
go mod init yellow
Then create a file yellow.go:
package yellow
func Mix(s string) string {
return s + "Yellow"
}
Then create a file orange/orange.go:
package main
import "yellow"
func main() {
s := yellow.Mix("Red")
println(s)
}
Then build:
go build
https://golang.org/doc/code.html

My main.go file cannot see other files

I need some help understanding what is wrong with my file layout in a simple web application.
$GOPATH/src/example.com/myweb
I then have 2 files:
$GOPATH/src/example.com/myweb/main.go
$GOPATH/src/example.com/myweb/api.go
Both files have:
package main
The api.go file looks like:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type API struct {
URI string
Token string
Secret string
client *http.Client
}
...
My main.go file looks like:
package main
import (
"github.com/gorilla/mux"
"html/template"
"net/http"
)
var (
templates = template.Must(template.ParseFiles("views/home.html", "views/history.html", "views/incident.html"))
api = API{
URI: "http://localhost:3000",
Token: "abc",
Secret: "123",
}
)
func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {
..
..
}
func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
..
..
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", WelcomeHandler)
r.PathPrefix("/assets/").Handler(
http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
http.ListenAndServe(":9000", r)
}
In the code I excluded, I basically use structs that are defined in my api.go file, and I get this error when doing:
go run main.go
# command-line-arguments
./main.go:16: undefined: API
./main.go:23: undefined: User
What exactly am I doing wrong here?
I tried changing the package name in api.go to myweb but that didn't help.
Am I suppose to use the package name myweb? Is just 1 file suppose to have main?
You're compiling only the main.go file. You should use:
go run main.go api.go
Or:
go run *.go
If you're writing a complex application, you might add everything to packages in subdirectories and have a single main.go file. For instance, etcd has an etcdmain subdirectory/package along with other subdirectories/packages. Something like:
/alarm
/auth
/cmd
/etcdmain
...
And the main.go file is simply:
package main
import "github.com/coreos/etcd/etcdmain"
func main() {
etcdmain.Main()
}
You are using golang workspace project, which is good for the structure for your application and it also standardize.
When we use the golang workspace, you can not run single go file. You need to call go build / go install.
Install
go install example.com/myweb
The command above will compile your main package on example.com/myweb. And the myweb executable binary will be placed on the GOPATH/bin. And you can run it manually.
Build
go build example.com/myweb
The command is similar to go install but the binary executable file will be placed on the current directory when you call the command, instead of on GOPATH/bin (unless your current directory is GOPATH/bin).
For more information please check this link.

Resources