Package imports, cannot use struct from imported package - go

This is probably a noob mistake but I cannot figure this out.
In main.go I am importing a package.
import(
"models/users"
)
// ...
func main() {
r.HandleFunc("/users/list", UsersModel.List())
The package is stored in src/models/users
The users package looks like this:
package users
import (
"gopkg.in/mgo.v2"
)
// ...
/**
* User Model
*/
type UsersModel struct {
}
// Add methods to the UsersModel type.
func (m *UsersModel) List() {
// ...
When I run the code I get the following error.
src\main.go:9: imported and not used: "models/users" src\main.go:20:
undefined: UsersModel
The go code appears to be valid as if I invalidate it throws an error. How do I export the UsersModel type from the users package?

You need to prefix your use of UsersModel with the package name users, like so:
um := users.UserModel{}
UsersModel.List() is also wrong: go doesn't have "static methods" or "class methods".

Related

Type error when importing vendored package

I am currently trying to export all shared components from multiple services to one new package and then reimporting this package to the services.
I quickly came accross the following problem:
In my utility package I create a function:
package utils
import "github.com/rs/zerolog"
func CreateLogger(logLevel string, w io.Writer) Logger {
...
return zerolog.New(w).With().Timestamp().Logger()
}
So now this package references "github.com/rs/zerolog"
Now in my services I want to use this method like this:
import "github.com/rs/zerolog"
var (
logger zerolog.Logger
)
func New() {
logger = utils.CreateLogger("info", os.Stdout)
}
Now this also references "github.com/rs/zerolog", but throws the error:
cannot use utils.CreateLogger("info", os.Stdout) (type "MY_REPO_PATH/vendor/VENDORED_REPO_PATH/vendor/github.com/rs/zerolog".Logger) as type "MY_REPO_PATH/vendor/github.com/rs/zerolog".Logger in assignment
So I understand why this is happening and I found a solution by wrapping the zerologger in my utils into a struct like this:
type Logger struct {
Logger zerolog.Logger
}
Now this works, but it is inconvenient because I have to call logger.Logger.Info()... instead of logger.Info() in my code.
It looks to me like this is not the perfect solution to this problem and I would like to know if there is a better way to solve it.
Best Regards,
Jonathan

How to access a struct from an external package in Go

I'm trying to import a struct from another package in the following file:
// main.go
import "path/to/models/product"
product = Product{Name: "Shoes"}
// models/product.go
type Product struct{
Name string
}
But in the main.go file the struct Product is undefined. How do I import the struct?
In Go you import "complete" packages, not functions or types from packages.
(See this related question for more details: What's C++'s `using` equivalent in golang)
See Spec: Import declarations for syntax and deeper explanation of the import keyword and import declarations.
Once you import a package, you may refer to its exported identifiers with qualified identifiers which has the form: packageName.Identifier.
So your example could look like this:
import "path/to/models/product"
import "fmt"
func main() {
p := product.Product{Name: "Shoes"}
// Use product, e.g. print it:
fmt.Println(p) // This requires `import "fmt"`
}

How to access flags outside of main package?

We parse flags in main.go which is in main package, of course. Then we have another package where we want to read some flag's value.
flags.Args() work fine, it will return all non-flag values.
But I cannot figure out to how read already parsed value for a flag in a package other than main.
Is it possible?
Thanks
Amer
I had the same requirement recently and I wanted a solution that avoided calling flag.Parse repeatedly in init functions.
Perusing the flag package I found Lookup(name string) which returns a Flag which has a Value. Every built in Value implements the flag.Getter interface. The call chain looks like this:
flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
If you mistype the flag name or use the wrong type you get a runtime error. I wrapped the lookup in a function that I call directly where needed since the lookup and get methods are fast and the function is not called often. So the main package declares the flag.
// main.go
package main
import "flag"
var httplog = flag.Bool("httplog", false, "Log every HTTP request and response.")
func main() {
flag.Parse()
// ...
}
And the utility package, which is decoupled from main except for the flag name, reads the flag value.
// httpdiag.go
package utility
import "flag"
func logging() bool {
return flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
}
You can define the var storing the flag in the separate package, as an exported variable, then call the flag parsing in the main package to use that variable, like this:
mypackage/const.go
var (
MyExportedVar string
)
mainpackage/main.go
func init() {
flag.StringVar(&mypackage.MyExportedVar, "flagName", "defaultValue", "usage")
flag.Parse()
}
This way, everybody can access that flag, including that package itself.
Note:
this only works for exported variables.
You can define the flag in that package and call flag.Parse() in func init(), flag.Parse can be called multiple times.
However, if you want to access the flag's value from multiple packages you have to expose it or create an exposed function to check it.
for example:
// pkgA
var A = flag.Bool("a", false, "why a?")
func init() {
flag.Parse()
}
// main package
func main() {
flag.Parse()
if *pkgA.A {
// stuff
}
}
Also you can use FlagSet.Parse(os.Args) if you want to reparse the args.
When you parse your flags, parse them into global variables which start with an initial Capital so they are public, eg
package main
var Species = flag.String("species", "gopher", "the species we are studying")
func main() {
flag.Parse()
}
Then in your other package you can refer to them as
package other
import "/path/to/package/main"
func Whatever() {
fmt.Println(main.Species)
}

How to persist "package" states in Go?

My goal is to encapsulate in one module/package.
Main package:
package main
import (
"github.com/zenazn/goji"
"./routes"
)
func main(){
routes.Setup()
goji.Serve()
}
And another package:
package routes
import "github.com/zenazn/goji"
func Setup() {
goji.Get("/static", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "static!")
})
}
How can I do this?
goji, in your example, is a package. Not a variable.
You cannot pass packages around like this.
If you look at the example on the goji github page
You simply just call goji.Get from your Init function, and goji.Serve from your main
route.go
package route
import "route"
import "github.com/zenazn/goji"
func Init(){
goji.Get("/hello/:name", hello)
}
main.go
package main
import "github.com/zenazn/goji"
func main(){
route.Init()
goji.Serve()
}
Packages in go export constants, variables, types and functions that have uppercase letters as their name. The package itself is not something directly manipulatable by the program.
The package goji should be exporting a variable named something like goji.Goji if you want to directly access it from other packages. A better solution is to provide some functions in the package that allow you to register your functions/helpers.
You could also export a function from goji like:
func Set(s string, func(w http.ResponseWriter, r *http.Request)) { ... }
that could be used by other packages:
goji.Set("/static", myFunc)
The error you had "use of package goji without selector" is saying you can't use the name of the package without specifying which exported value you want from the package. It's expecting goji.something not goji by itself.
The function init() inside go files has special properties: see http://golang.org/ref/spec#Program_initialization_and_execution

Can't use struct from own package

I created following file structure in $GOPATH/src
bitbucket.org/MyName/ProjectName
I have follwoing files here
ProjectName
- controllers/
- meController.go
- app.go
In app.go I'm importing my controller like that:
import "bitbucket.org/MyName/ProjectName/controllers"
And in main func I'm trying to use it's method.
meController = new(controllers.meController)
m.Get("/", meController.Index)
My meController.go looks like this
package controllers
type meController struct {
}
func (controller *meController) Index () string {
return "Hello World"
}
But I'm getting this error:
./app.go:5: imported and not used: "bitbucket.org/MyName/ProjectName/controllers"
./app.go:12: undefined: meController
I don't have any idea how to get this to work.
Any ideas?
Thanks!
In Go, every symbol that starts with lowercase is not exported by the package. call your struct MeController and you'll be fine.

Resources