I am new to go module building. What im trying to do is to create a go library with commonly used methods that other developers can use in their go code.
So first in my internal github, Ive created a repo https://internalgithub/<org>/lib-go.git
The repo structure looks like
$ tree
.
├── README.md
├── go.mod
├── go.sum
└── main.go
And the main.go file has the following content
package main
import (
"flag"
"os"
"path/filepath"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
func main() {}
func someFunctinDevelopersNeed(cluster bool) kubernetes.Interface {
if cluster == false {
var kubeconfig *string
.
.
return clientset
}
The code is available in the master branch of my org github.
The next task to to write code that invokes this library and in turn invokes the methid someFunctinDevelopersNeed
So in my app code, my main.go looks like
package main
import "internalgithub/<org>/lib-go"
func main() {
clientset = someFunctinDevelopersNeed()
.
.
}
But when I try to do go get -t -v internalgithub/<org>/lib-go, I get
runtime.main_main·f: function main is undeclared in the main package
Is there something I have missed ?
EDIT:
Based on suggestions, now I have done the following
$ tree
.
├── README.md
├── go.mod
├── go.sum
└── kubernetes
└── kubernetes.go
And kubernetes.go starts with
package kubernetes
import (
"flag"
"os"
"path/filepath"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
func someFunctinDevelopersNeed(cluster bool) kubernetes.Interface {
if cluster == false {
var kubeconfig *string
.
.
return clientset
}
Even with these changes, I run into the same error
If you write your own library, do not add main package.
You can see some popular golang libraries, like go-gin(uses gin.go ), gorm (uses gorm.go)
For your case, if you just want to create a collection for most commonly used functions, you can add a package utils and put your implementation into utils.go or other xxx.go files
Related
Hope find answers here. I'm trying a simple Cobra cli application with tree structure as below
├── cmd1
│ └── root.go
├── go.mod
├── go.sum
└── main.go
and the main.go:
package main
package main
import (
"iptracker/cmd1"
)
func main() {
cmd1.Execute()
}
cmd1/root.go:
package cmd1
import (
"github.com/spf13/cobra"
)
var (
rootCmd = &cobra.Command{
Use: "Cobra",
Short: "Iptracker app",
Long: "IpTracker app",
}
)
func Execute() error {
return rootCmd.Execute()
}
My go.mod file:
module iptracker
go 1.19
require github.com/spf13/cobra v1.6.1
require (
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
When I try running the code I get the following error:
main.go:4:2: package iptracker/cmd1 is not in GOROOT (/usr/local/go/src/iptracker/cmd1)
Go ENV configured correctly
GOPATH: /home/username/Go
GOROOT: /usr/local/go
I have run
go mod init iptracker
go mod tidy
But no luck. Don't know what I'm missing. I appreciate all your help. Thank you!
maybe you should write you go.mod file like this:
module iptracker
go 1.18
require github.com/spf13/cobra v1.6.1
I am trying to use a Golang parser generated by Antlr. but when I try to access it in my main file, it gives me the following error: build command-line-arguments: cannot find module for path path/to/parser my main file is this:
package main
import (
"fmt"
"./parser"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
func main() {
fmt.Println("Hello, World!")
is := antlr.NewInputStream("1 + 2 * 3")
// Create the Lexer
lexer := parser.NewHelloWorldLexer(is)
// Read all tokens
for {
t := lexer.NextToken()
if t.GetTokenType() == antlr.TokenEOF {
break
}
fmt.Printf("%s (%q)\n",
lexer.SymbolicNames[t.GetTokenType()], t.GetText())
}
}
Here is solution using go modules
Your project structure should look like this
.
├── go.mod
├── main.go
└── parser
└── parser.go
go.mod
module example.com/projectname
go 1.15
...
main.go
package main
import (
"fmt"
"example.com/projectname/parser"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
...
parser.go
package parser
import (
"github.com/antlr/antlr4/runtime/Go/antlr"
)
...
My intention is to mention local package in go.mod file, but stuck in package version part. (Go version is go1.14.4 linux/amd64)
Error:
arun#debian:~/experiments$ go build
go: errors parsing go.mod:
/home/arun/experiments/go.mod:8: usage: require module/path v1.2.3
If blindly give a version number (for example : github.com/kcarun/local_pkg/app v1.2.3 in go.mod, it gives unknown version error) while executing go build
go.mod:
module github.com/kcarun/gitlandfill
go 1.14
replace github.com/kcarun/local_pkg/ => /home/arun/experiments/local_pkg/
require (
github.com/kcarun/local_pkg/app
)
main.go:
package main
import "fmt"
import "local_pkg"
func main(){
fmt.Println("Ok")
app.SayHello()
}
app.go:
package app
import "fmt"
func SayHello(){
fmt.Println("Is working!!")
}
Directory Structure :
arun#debian:~/experiments$ pwd
/home/arun/experiments
arun#debian:~/experiments$ tree
.
|-- go.mod
|-- local_pkg
| `-- app.go
`-- main.go
Right way to import "local" package as
.
├── go.mod
├── local_pkg
│ └── app.go
└── main.go
is
package main
import "fmt"
import "github.com/kcarun/gitlandfill/local_pkg"
func main(){
fmt.Println("Ok")
local_pkg.SayHello()
}
, without declared it in go.mod:
module github.com/kcarun/gitlandfill
go 1.14
If the package declared different than directory name (for example: dir is /home/arun/experiments/local_pkg and pages is app), you should import package use directory name, but to call it use package name:
package main
import "fmt"
import "github.com/kcarun/gitlandfill/local_pkg"
func main(){
fmt.Println("Ok")
app.SayHello()
}
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
I'm trying to solve a dependency problem : let's say I want to keep the code in my main.go totally decoupled from my database, I created 2 packages for that : dummy & postgres.
/app/
-- main.go
/dummy/
-- dummy.go
/postgres/
-- postgres.go
Everything is working fine, I just have to select in my main.go which package I would like to import to get a behavior or another... but is there a way to choose that when building main.go ?
If there's a more idiomatic way to achieve this, I'm of course very interested !
You can utilize the Go conditional build via build tags and target your compilation of main.go.
Refer this article and put your thoughts into action.
For Example:
Directory structure
build-tags
├── build-tags
├── dummy
│ └── dummy.go
├── main_dummy.go
├── main_postgres.go
└── postgres
└── postgres.go
Sample implementation:
dummy/dummy.go
package dummy
import "fmt"
func PrintName() {
fmt.Println("My name is dummy package")
}
postgres/postgres.go
package postgres
import "fmt"
func PrintName() {
fmt.Println("My name is postgres package")
}
main_dummy.go
// +build dummy
package main
import "build-tags/dummy"
func main() {
dummy.PrintName()
}
postgres.go
// +build postgres
package main
import "build-tags/postgres"
func main() {
postgres.PrintName()
}
Now let's build targeting dummy tag, same way you can do for postgres tag.
go build --tags="dummy"
# run the program
./build-tags
My name is dummy package