A factory code autogenator for Go
go install github.com/jotadrilo/go-factory
mkdir -p go-factory && \
curl -sSL https://github.com/jotadrilo/go-factory/releases/download/1.0.3/go-factory_1.0.3_linux_x86_64.tar.gz | tar xzf - -C go-factory && \
sudo cp go-factory/go-factory /usr/local/bin/ && \
sudo chmod +x /usr/local/bin/go-factory
Homebrew users:
brew tap jotadrilo/tap
brew install jotadrilo/tap/go-factory
Alternative:
mkdir -p go-factory && \
curl -sSL https://github.com/jotadrilo/go-factory/releases/download/1.0.3/go-factory_1.0.3_darwin_arm64.tar.gz | tar xzf - -C go-factory && \
sudo cp go-factory/go-factory /usr/local/bin/ && \
sudo chmod +x /usr/local/bin/go-factory
You can configure go-factory by adding annotations to your Go files,
or placing a .gofactory.yaml
configuration file in your project root directory.
See the examples section.
You can annotate your structs with //go:generate go-factory -n Name
The program will auto-detect any .gofactory.yaml
file in your project root directory (a directory
from your current directory to the filesystem root directory with a go.mod
file inside) or in your
current directory.
You can specify one with the --config
or -c
flag.
The configuration file must include a configuration section per package.
External packages are not supported.
packages:
- name: 'github.com/jotadrilo/go-factory/examples'
- name: 'github.com/jotadrilo/go-factory/examples/inner'
factory_file_tpl: '{{ .ProjectDir }}/{{ .PackageDirRel }}/{{ .Filename }}_factory.go'
include:
- A
- B
exclude:
- C
- D
Parameter | Description |
---|---|
packages |
Array of packages configuration |
packages[n].name |
Name of the package to generate factories for |
packages[n].factory_file_tpl |
Go template to configure the factory file output location and name. Default: '{{ .ProjectDir }}/{{ .PackageDirRel }}/{{ .Filename }}_factory.go' |
packages[n].include |
Array of struct names to include in the generation. Default: [] |
packages[n].exclude |
Array of struct names to exclude from the generation. Default: [] |
If both include
and exclude
parameters are blank, it will generate factories for all structs in the package.
Let's use the example examples/inner/foo.go
in this project, assuming that I have cloned the project
in /home/user/go-factory
:
This template can be configured with the following parameters:
Parameter | Description | Example |
---|---|---|
ProjectDir |
Project directory | /home/user/go-factory |
PackageName |
Name of the package | inner |
PackageDirRel |
Relative path to the directory of the package | examples/inner |
TypeName |
Name of the struct type | For Foo struct: Foo |
Filename |
Name of the file declaring the struct, without its extension | For Foo struct: foo |
package examples
//go:generate go-factory -n A
type A struct {
Bool bool
String string
}
//go:generate go-factory -n B
type B struct {
Name string
}
//go:generate go-factory -n C
type C struct {
A *A
B *B
As []*A
Bs []*B
}
Generates:
// Code generated by go-factory 1.0.2; DO NOT EDIT.
package examples
// FactoryC is a helper factory to ease creating data of type C
type FactoryC struct {
Factory C
}
func NewFactoryC() *FactoryC {
return &FactoryC{}
}
func (f *FactoryC) WithA(value *A) *FactoryC {
f.Factory.A = value
return f
}
func (f *FactoryC) WithB(value *B) *FactoryC {
f.Factory.B = value
return f
}
func (f *FactoryC) WithAs(values ...*A) *FactoryC {
f.Factory.As = values
return f
}
func (f *FactoryC) AddAs(values ...*A) *FactoryC {
f.Factory.As = append(f.Factory.As, values...)
return f
}
func (f *FactoryC) WithBs(values ...*B) *FactoryC {
f.Factory.Bs = values
return f
}
func (f *FactoryC) AddBs(values ...*B) *FactoryC {
f.Factory.Bs = append(f.Factory.Bs, values...)
return f
}
func (f *FactoryC) Build() *C {
return deepCopyC(&f.Factory)
}
func deepCopyC(src *C) *C {
if src == nil {
return nil
}
copyInstance := *src
if src.A != nil {
copyInstance.A = new(A)
*copyInstance.A = *src.A
}
if src.B != nil {
copyInstance.B = new(B)
*copyInstance.B = *src.B
}
if src.As != nil {
copyInstance.As = make([]*A, len(src.As))
copy(copyInstance.As, src.As)
}
if src.Bs != nil {
copyInstance.Bs = make([]*B, len(src.Bs))
copy(copyInstance.Bs, src.Bs)
}
return ©Instance
}