I have folder structure like this:
> validations
> user
> user.validation.go
> address
> address.validation.go
the package name for those two file is validations
inside user.validation.go
I try to use the address validation struct like this:
type UserValidation struct {
Address AddressValidation // the error says: undeclared name: AddressValidation
}
and I have tried calling package name before struct like this:
type UserValidation struct {
Address validations.AddressValidation // the error says: undeclared name: validations
}
and I have tried to import it first:
import "example/go-api/validations"
and the error says: AddressValidation not declared by package validations
CodePudding user response:
You have three separate packages in each of these folders:
validations
user
address
The validations
folder contains only other packages so is not able to be usefully imported; it contains no code with any exports.
The user
folder also contains a package named validations
this can usefully imported to access the exported UserValidation
type.
The address
folder also contains a package named validations
this can be usefully imported to access the exported AddressValidation
type.
But GoLang does not treat these as all forming a single validations
package. A 'package' is a namespace, but packages with the same name are not the same namespace. They all remain separate and distinct packages (and namespaces).
If the validations
package in the user
folder wishes to import the validations
package in the address
folder it can do so but must reference the full path to that package and must alias the import since the folder name does not match the name of the package it contains:
import validations "example/go-api/validations/address"
type UserValidation struct {
Address validations.AddressValidation
}
will work just fine.
But note that since this involves an alias, that alias can be anything you like - it doesn't have to match the name of the imported package. i.e. this is just as valid:
import v "example/go-api/validations/address"
type UserValidation struct {
Address v.AddressValidation
}
If some other package in your project wishes to reference both UserValidation
and AddressValidation
it must import both of the separate validations
packages that contain them and provide unique aliases for each:
import (
addressValidations "example/go-api/validations/address"
userValidations "example/go-api/validations/user"
)
and may then do something like:
var (
av addressValidations.AddressValidation
uv userValidations.UserValidation
)
The key to all of this is that folders are not a way of organising files within a package. A folder is a package.
Unless you have a specific reason for doing otherwise it is best to:
- Name a package for the folder that contains its files
- Use unique names for packages (in the same project/module)
There are occasional, valid exceptions to rule #2, e.g. where a package name makes sense in two different and mutually exclusive contexts. i.e. where no other package would never wish or need to import different packages of the same name from those different contexts.
I've yet to encounter a valid exception to rule #1. :)
Possible Alternative Approach
If you really want to keep UserValidation
and AddressValidation
in separate packages, you could name the packages user
and address
(i.e. apply rule #1: name each package for their respective folders).
Then, since the package name provides the address or user context for the symbols within them, you can rename the types to simply Validation
in each case.
Your user.go
code then becomes:
package user
import "example/go-api/validations/address"
type Validation struct {
Address address.Validation
}
and your address.go
code:
package address
type Validation struct {}
and variables in a package that imports both user
and address
validations become:
import (
"example/go-api/validations/address"
"example/go-api/validations/user"
)
var (
av address.Validation
uv user.Validation
)
Caveat Coder
This is not a prescription! Without knowing more about your specific use case I have no idea whether this is the best way to skin this particular feline; it is merely an illustration of one way.
In short: use your folder/package names to help add context and meaning to the symbols exported by your packages.