How to access a struct from an external package in Go - 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"`
}

Related

Two go files having package declaration main inside a package

So i have created a package named app inside which there are two go files named entry.go and entry1.go where entry.go is having function main while entry1.go is having a function which is being called by entry.go.
content of entry.go:
package main
import "fmt"
import "app"
func main(){
fmt.Println("app/entry.go")
app.FunctionOne()
}
content of entry1.go:
package main
func FunctionOne() {
fmt.Println("this is having different name")
}
on running go build it shows import cycle
You don't have to import app! you're in the same package which is main package.
just remove the extra import, and use FunctionOne() no need for app

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

Implement interface using custom type without importing package

Suppose there's a 3rd party package that makes an interface available:
package giantpackage
type UselessInfo struct {
wontUse string
alsoWontUse string
}
type CoolInterface interface {
DoSomethingAwesome(ui UselessInfo) (string, error)
}
It seems easy to implement as such:
package main
import giantpackage
type Jedi struct {
name string
age int
}
func (j Jedi) DoSomethingAwesome(ui giantpackage.UselessInfo) (string, error)
return "Hello world.", nil
}
Assuming:
1) I don't actually use the UselessInfo struct in my DoSomethingAwesome function.
2) The package that I have to import is HUGE.
3) The package that I have to import is no longer maintained, and cannot be modified.
My question:
Is there any way to implement CoolInterface without importing giantpackage?
There is not.
To implement the giantpackage.CoolInterface, your type must have a method:
DoSomethingAwesome(giantpackage.UselessInfo) (string, error)
And to have a method that matches this signature, you have to import giantpackage, else using any other type for the parameter, it won't match the required method.
In your comments you indicated you plan to create a library, and providing an implementation of this interface will be a "nice to have" feature to some of the users of your library.
Then the recommended way is to create a "core" package of your library which does not contain this interface implementation and thus does not depend on giantpackage. Users of your library that do not need this will only import your "core" package and so they will also not depend on giantpackage.
Create another "extension" package of your library which will contain the implementation of this interface (and which may also use your "core" package if needed). Users that do need this can import this package as well.

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

Package imports, cannot use struct from imported package

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".

Resources