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
Related
I'm a bit confused why Go test won't work properly.
├── datasource
│ ├── cache.go
│ ├── database.go
│ ├── datasource.go
│ └── datasource_test.go
├── main.go
└── README.md
This is my file directory structure.
I have inside datasource_test.go implemented this https://golang.org/pkg/testing/
i.e.,
package datasource
import "testing"
func TestAbs(t *testing.T) {
got := Abs(-1)
if got != 1 {
t.Errorf("Abs(-1) = %d; want 1", got)
}
}
my main directory is like this,
package main
import "datasource/datasource.go"
func main() {
//
}()
}
}
What am I missing here? I assume it's due to not import.
You can use go test ./... to test all packages. The way you import the packages is wrong as well as you don't need to import the packages for testing purposes. go test command will help you run your tests.
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
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()
}
everyone, I'm confused by what I'm seeing; I have the following tree:
├── go.mod
├── main.go
└── server
├── server.go
└── server_integration_test.go
Let's say my module name (mod.go) is gotest. Content of server.go:
package server
type MyStruct struct {
Hello string
}
func (m MyStruct) SayHello() string {
return m.Hello
}
Contents of server_integration_test.go:
package server_integration_test
import (
"testing"
)
func TestIntegration(t *testing.T) {
t.Errorf("just gonna fail!")
}
And finally my main.go`:
package main
import (
"fmt"
"gotest/server"
)
func main() {
my := server.MyStruct{Hello: "my-struct"}
fmt.Println("from mystruct", my.SayHello())
}
When I run go build (or go test ./...), I receive the following error:
main.go:5:2: found packages server (server.go) and server_integration (server_integration_test.go) in /tmp/gotest/server
But if I change my server_integration_test.go to be:
package server_test
// ...
Everything works.
Can someone please explain what's happening here?
The supported package names for server package tests are server and server_test.
See test packages:
'Go test' recompiles each package along with any files with names matching the file pattern "*_test.go". These additional files can contain test functions, benchmark functions, and example functions. ...
Test files that declare a package with the suffix "_test" will be compiled as a separate package, and then linked and run with the main test binary.
The _test suffix is applied to the name of the package under test (the documentation can be improved to make this fact more explicit).
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