main_test.go
package main_test
import (
"log"
"os"
"testing"
"."
)
func TestMain(m *testing.M) {
a = main.App{}
a.Init(
os.Getenv("TEST_DB_USERNAME"),
os.Getenv("TEST_DB_PASSWORD"),
os.Getenv("TEST_DB_NAME"))
ensureTableExists()
code := m.Run()
clearTable()
os.Exit(code)
}
app.go
package main
import (
"database/sql"
"fmt"
"log"
"github.com/gorilla/mux"
_ "github.com/lib/pq"
)
type App struct {
Router *mux.Router
DB *sql.DB
}
func (a *App) Init(user, password, dbname string) {
connection := fmt.Sprintf("user=%s password=%s dbname=%s", user, password, dbname)
var err error
a.DB, err = sql.Open("postgres", connection)
if err != nil {
log.Fatal(err)
}
a.Router = mux.NewRouter()
}
func (a *App) Run(addr string) { }
main.go
package main
import "os"
func main() {
a := App{}
a.Init(
os.Getenv("APP_DB_USERNAME"),
os.Getenv("APP_DB_PASSWORD"),
os.Getenv("APP_DB_NAME"))
a.Run(":8080")
}
Hey everyone, I am brand new to Golang and working with some tutorials. In the tutorial, they are using the import statement "." which is throwing an error for me. The exact error is "Non-canonical import-path." I tried using a relative path and full path to access the main file in my project but when I use anything other than "." the var a.main.App throws an error saying that main is an unresolved type. My $GOPATH is set to c:/users/me/go/src my project lives in the src folder. I am not entirely sure what is wrong my code at the moment. If it is something glaringly obvious I apologize.
Here is what I am trying to import. This lives in a file called app.go which is called through main.go
type App struct {
Router *mux.Router
DB *sql.DB
}
You don't need to import main for using struct App. You simply change the package of main_test to main then you can able to use that struct, like below i simply passed the main_test file.
package main
import (
"os"
"testing"
)
func TestMain(m *testing.M) {
a := App{}
a.Init(
os.Getenv("TEST_DB_USERNAME"),
os.Getenv("TEST_DB_PASSWORD"),
os.Getenv("TEST_DB_NAME"))
ensureTableExists()
code := m.Run()
clearTable()
os.Exit(code)
}
Here what i get from execute the test:
Success: Tests passed.
Related
I'm trying to import a func from a subfolder.
I have a main package
package main
import (
...
)
func handleRequests() {
http.HandleFunc("/health", health)
...
}
func main() {
handleRequests()
}
And then I have a folder called health in which I have a file called health.go.
package health
import (
...
)
func health(writer http.ResponseWriter, _ *http.Request) {
...
}
What shall my import look like and how do I call my health func?
At this point, your import statement doesn't mean anything, because it health package has no exported function or variable. You should check out the scoping in Go from the language spec. From here
Maybe consider checking out go modules, since it is now the suggested way to handle any go program that has more than a file.
The quick answer is,
your health.go
package health
import (
...
)
func Handler(writer http.ResponseWriter, _ *http.Request) {
...
}
your main.go
package main
import (
github.com/blablabla/yourproject/health
)
func handleRequests() {
http.HandleFunc("/health", health.Handler)
...
}
func main() {
handleRequests()
}
You must name function starting from uppercase symbol ("Health" instead of "health").
For example: health (your case) is private declaration, and Health would be public.
The same principle with types and variables naming.
I'm having difficulty when trying to get path of imported package. When I print result of os.Getwd() inside imported package, it's showing same path like on main package.
This what I did.
Project structure
lib/lib.go
package lib
import "os"
import "fmt"
func init() {
dir, _ := os.Getwd()
fmt.Println("lib.init() :", dir)
}
func GetPath() {
dir, _ := os.Getwd()
fmt.Println("lib.GetPath() :", dir)
}
main.go
package main
import "os"
import "fmt"
import "test-import/lib"
func main() {
dir, _ := os.Getwd()
fmt.Println("main :", dir)
lib.GetPath()
}
Result
lib.init() : /Users/novalagung/Documents/go/src/test-import
main : /Users/novalagung/Documents/go/src/test-import
lib.GetPath() : /Users/novalagung/Documents/go/src/test-import
The result of os.Getwd() from lib/lib.go is still same path like on main. What I want is the real path of the package which is /Users/novalagung/Documents/go/src/test-import/lib/
What should I do? Is it possible?
If you can get a reference to something in the package, you can use reflect to get the import path.
Here's an example on Play:
package main
import (
"bytes"
"fmt"
"reflect"
)
func main() {
var b bytes.Buffer
fmt.Println(reflect.TypeOf(b).PkgPath())
}
PkgPath() only can retrieve the package path for non-pointer
// If the type was predeclared (string, error) or not defined (*T, struct{},
// []int, or A where A is an alias for a non-defined type), the package path
// will be the empty string.
func packageName(v interface{}) string {
if v == nil {
return ""
}
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
return val.Elem().Type().PkgPath()
}
return val.Type().PkgPath()
}
I am new in Golang and need some help.
As you can see in the code below I am tring to create REST API in Golang. I use mux (Gorilla Mux) and pq (PostgreSQL driver) as third party libraries. Don't want to use ORM.
Inside application.go file I have InitializeRoutes function with a list of all aviable routes. GetFactors function process one of these routes. I am tring to define GetFactors function logic in other file called factors.go. Inside factors.go file I want to use Application struct which was defined in application.go. How to make it correctly? Right now as you can see they are in different packages. For thats why factors.go file don't see Application struct.
Project structure:
main.go
application.go
controllers
factors.go
main.go:
package main
func main() {
application := Application{}
application.Initialization()
application.Run("localhost:8000")
}
application.go:
package main
import (
"database/sql"
"github.com/gorilla/mux"
"log"
"net/http"
"rest-api/configurations"
)
type Application struct {
Router *mux.Router
Database *sql.DB
}
func (application *Application) Initialization() {
var err error
application.Database, err = configurations.DatabaseConnection()
if err != nil {
log.Fatal(err)
}
application.Router = mux.NewRouter()
application.Router.StrictSlash(true)
application.InitializeRoutes()
}
func (application *Application) Run(address string) {
log.Fatal(http.ListenAndServe(address, application.Router))
}
func (application *Application) InitializeRoutes() {
application.Router.HandleFunc("/api/factors", application.GetFactors).Methods("GET")
// other code
}
controllers/factors.go:
package controllers
import (
"net/http"
)
func (application *Application) GetFactors(rw http.ResponseWriter, request *http.Request) {
// code
}
Well, finally I decided to redesign the project structure.
main.go
routes
routes.go
controllers
factors.go
models
factors.go
main.go:
import (
"your_project_name/routes"
)
func main() {
// code
router := mux.NewRouter()
routes.Use(router)
// code
}
routes/routes.go:
package routes
import (
"github.com/gorilla/mux"
"your_application_name/controllers"
)
func Use(router *mux.Router) {
router.HandleFunc("/api/factors", controllers.GetFactors).Methods("GET")
}
controllers/factors.go:
package controllers
var GetFactors = func(res http.ResponseWriter, req *http.Request) {
// code
}
I'm trying to build a Go project using the layout as described in Go Project Layout
I'm using go 1.9.2 on Ubuntu. My project layout is as follows
$GOPATH/src/github.com/ayubmalik/cleanprops
/cmd
/cleanprops
/main.go
/internal
/pkg
/readprops.go
The file cmd/cleanprops/main.go is referring to the cleanprops package i.e.
package main
import (
"fmt"
"github.com/ayubmalik/cleanprops"
)
func main() {
body := cleanprops.ReadProps("/tmp/hello.props")
fmt.Println("%s", body)
}
The contents of internal/pkg/readprops.go are:
package cleanprops
import (
"fmt"
"io/ioutil"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func ReadProps(file string) string {
body, err := ioutil.ReadFile(file)
check(err)
fmt.Println(string(body))
return body
}
However when I build cmd/cleanprops/main.go, from inside directory $GOPATH/src/github.com/ayubmalik/cleanprops, using command:
go build cmd/cleanprops/main.go
I get the following error:
cmd/cleanprops/main.go:5:2: no Go files in /home/xyz/go/src/github.com/ayubmalik/cleanprops
What am I missing?
The document suggests this structure:
$GOPATH/src/github.com/ayubmalik/cleanprops
/cmd
/cleanprops
/main.go
/internal
/pkg
/cleanprops
/readprops.go
Import the package like this. The import path matches the directory structure below $GOPATH/src.
package main
import (
"fmt"
"github.com/ayubmalik/cleanprops/internal/pkg/cleanprops"
)
func main() {
body := cleanprops.ReadProps("/tmp/hello.props")
fmt.Println("%s", body)
}
I've decided to try breaking my project into a MVC type view, so to start I wanted to put all my routing into a controller folder and I put my database connection into another folder titled db.
I can't figure out how to make the database connection work smoothly. Back when all of the files were in my package main I just called InitDb() in main and in all of my other files in the main package I had access to the db variable. Now that I made db it's down package and imported it, nothing is recognized.
I also don't know where to call InitDb() and defer db.Close() anymore since it's not all in main.
db/db.go
package database
import (
"fmt"
"database/sql"
)
var db *sql.DB
const (
dbhost = "localhost"
dbuser = "root"
dbpass = "password"
dbname = "user"
)
func InitDb() {
var err error
connectionString := fmt.Sprintf("%s:%s#/%s", dbuser, dbpass, dbname)
db, err = sql.Open("mysql", connectionString)
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected!")
}
controllers/index.go
package controllers
import (
"net/http"
"fmt"
"db"
"github.com/gorilla/mux"
)
func TestHandler(r *mux.Router)
r.HandleFunc("/index", test).Methods("GET")
}
func test(w http.ResponseWriter, r *http.Request) {
// database undefined
err := database.QueryRow("some sql statement")
CheckErr(err)
}
main.go
package main
import (
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
controllers.TestHandler(r)
log.Fatal(http.ListenAndServe("localhost:8000", r))
}
While not required it is a good idea to have the package name be the same as the folder in which it lives, so either do:
db/db.go
package db
// ...
Or do:
database/db.go
package database
// ...
I would not recommend mixing the two.
You can have your database package export a Close function and have main call it when it's done.
database/db.go
package database
import (
"fmt"
"database/sql"
)
var db *sql.DB
func Close() {
db.Close()
}
// ...
main.go
package main
import "database"
func main() {
defer database.Close()
// ...
}
Or just don't close it in this case. When main exits the *sql.DB does not stay alive outside your program, it will not take up connection slots if the program is not running. Closing makes sense only if you're using multiple instances of *sql.DB and there is danger that they will start blocking while waiting for a connection. If you have only one that's shared by the whole program then you should be ok not calling defer close.