[![Build Status](https://travis-ci.org/dave/jennifer.svg?branch=master)](https://travis-ci.org/dave/jennifer) [![Go Report Card](https://goreportcard.com/badge/github.com/dave/jennifer)](https://goreportcard.com/report/github.com/dave/jennifer) [![codecov](https://img.shields.io/badge/codecov-100%25-brightgreen.svg)](https://codecov.io/gh/dave/jennifer) ![stability-stable](https://img.shields.io/badge/stability-stable-brightgreen.svg) [![Sourcegraph](https://sourcegraph.com/github.com/dave/jennifer/jen/-/badge.svg)](https://sourcegraph.com/github.com/dave/jennifer?badge) # Jennifer Jennifer is a code generator for Go. ```go package main import ( "fmt" . "github.com/dave/jennifer/jen" ) func main() {{ "ExampleNewFile" | code }} ``` Output: ```go {{ "ExampleNewFile" | output }} ``` ### Install ``` go get -u github.com/dave/jennifer/jen ``` ### Need help? If you get stuck, have a question, would like a code review, or just want a chat: I'm happy to help! Feel free to open an issue, email me or mention @dave in your PR. ### Examples Jennifer has a comprehensive suite of examples - see [godoc](https://godoc.org/github.com/dave/jennifer/jen#pkg-examples) for an index. Here's some examples of jennifer being used in the real-world: * [genjen](genjen/render.go) (which generates much of jennifer, using data in [data.go](genjen/data.go)) * [zerogen](https://github.com/mrsinham/zerogen/blob/master/generator.go) * [go-contentful-generator](https://github.com/nicolai86/go-contentful-generator) ### Rendering For testing, a File or Statement can be rendered with the fmt package using the %#v verb. {{ "ExampleCall_fmt" | example }} This is not recommended for use in production because any error will cause a panic. For production use, [File.Render](#render) or [File.Save](#save) are preferred. # Identifiers **Identifiers** [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Id {{ "Id" | doc }} {{ "ExampleId" | example }} ### Dot {{ "Dot" | doc }} {{ "ExampleDot" | example }} ### Qual {{ "Qual[0]" | doc }} {{ "ExampleQual" | example }} {{ "Qual[1:4]" | doc }} {{ "ExampleQual_file" | example }} {{ "Qual[4:]" | doc }} ### List {{ "List" | doc }} {{ "ExampleList" | example }} # Keywords [Identifiers](#identifiers) **Keywords** [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Simple keywords, predeclared identifiers and built-in functions are self explanatory: | Construct | Name | | ---------------- | ---- | | Keywords | Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var | | Functions | Append, Cap, Close, Complex, Copy, Delete, Imag, Len, Make, New, Panic, Print, Println, Real, Recover | | Types | Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr | | Constants | True, False, Iota, Nil | | Helpers | Err | Built-in functions take a list of parameters and render them appropriately: {{ "ExampleAppend_more" | example }} Special cases for [If, For](#if-for), [Interface, Struct](#interface-struct), [Switch, Case](#switch-select), [Return](#return) and [Map](#map) are explained below. # Operators [Identifiers](#identifiers) [Keywords](#keywords) **Operators** [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) {{ "Op" | doc }} {{ "ExampleOp" | example }} {{ "ExampleOp_star" | example }} {{ "ExampleOp_variadic" | example }} {{ "ExampleOp_complex_conditions" | example }} # Braces [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) **Braces** [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods render curly braces, summarized below: | Name | Prefix | Separator | Example | | ------------------------------ | ------------ | --------- | -------------------------------------| | [Block](#block) | | `\n` | `func a() { ... }` or `if a { ... }` | | [Interface](#interface-struct) | `interface` | `\n` | `interface { ... }` | | [Struct](#interface-struct) | `struct` | `\n` | `struct { ... }` | | [Values](#values) | | `,` | `[]int{1, 2}` or `A{B: "c"}` | ### Block {{ "Block[:2]" | doc }} {{ "ExampleBlock" | example }} {{ "ExampleBlock_if" | example }} {{ "Block[2:]" | doc }} [See example](#switch-select). ### Interface, Struct Interface and Struct render the keyword followed by a statement list enclosed by curly braces. {{ "ExampleInterface_empty" | example }} {{ "ExampleInterface" | example }} {{ "ExampleStruct_empty" | example }} {{ "ExampleStruct" | example }} # Parentheses [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) **Parentheses** [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods output parenthesis, summarized below: | Name | Prefix | Separator | Example | | ----------------- | ------ | --------- | --------------------------------- | | [Call](#call) | | `,` | `fmt.Println(b, c)` | | [Params](#params) | | `,` | `func (a *A) Foo(i int) { ... }` | | [Defs](#defs) | | `\n` | `const ( ... )` | | [Parens](#parens) | | | `[]byte(s)` or `a / (b + c)` | | [Assert](#assert) | `.` | | `s, ok := i.(string)` | ### Call {{ "Call" | doc }} {{ "ExampleCall" | example }} ### Params {{ "Params" | doc }} {{ "ExampleParams" | example }} ### Defs {{ "Defs" | doc }} {{ "ExampleDefs" | example }} ### Parens {{ "Parens" | doc }} {{ "ExampleParens" | example }} {{ "ExampleParens_order" | example }} ### Assert {{ "Assert" | doc }} {{ "ExampleAssert" | example }} # Control flow [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) **Control flow** [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### If, For If and For render the keyword followed by a semicolon separated list. {{ "ExampleIf" | example }} {{ "ExampleFor" | example }} ### Switch, Select Switch, Select, Case and Block are used to build switch or select statements: {{ "ExampleSwitch" | example }} ### Return {{ "Return" | doc }} {{ "ExampleReturn" | example }} # Collections [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) **Collections** [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Map {{ "Map" | doc }} {{ "ExampleMap" | example }} ### Index {{ "Index" | doc }} {{ "ExampleIndex" | example }} {{ "ExampleIndex_index" | example }} {{ "ExampleIndex_empty" | example }} ### Values {{ "Values" | doc }} {{ "ExampleValues" | example }} {{ "Dict" | doc }} {{ "ExampleValues_dict_multiple" | example }} {{ "ExampleValues_dict_composite" | example }} {{ "DictFunc[0]" | doc }} {{ "ExampleDictFunc" | example }} Note: the items are ordered by key when rendered to ensure repeatable code. # Literals [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) **Literals** [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Lit {{ "Lit" | doc }} {{ "ExampleLit" | example }} {{ "ExampleLit_float" | example }} {{ "LitFunc[1:2]" | doc }} {{ "ExampleLitFunc" | example }} For the default constant types (bool, int, float64, string, complex128), Lit will render the untyped constant. | Code | Output | | ------------- | ---------- | | `Lit(true)` | `true` | | `Lit(1)` | `1` | | `Lit(1.0)` | `1.0` | | `Lit("foo")` | `"foo"` | | `Lit(0 + 1i)` | `(0 + 1i)` | For all other built-in types (float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, complex64), Lit will also render the type. | Code | Output | | ------------------------ | ------------------- | | `Lit(float32(1))` | `float32(1)` | | `Lit(int16(1))` | `int16(1)` | | `Lit(uint8(0x1))` | `uint8(0x1)` | | `Lit(complex64(0 + 1i))` | `complex64(0 + 1i)` | The built-in alias types byte and rune need a special case. LitRune and LitByte render rune and byte literals. | Code | Output | | ------------------------ | ----------- | | `LitRune('x')` | `'x'` | | `LitByte(byte(0x1))` | `byte(0x1)` | # Comments [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) **Comments** [Helpers](#helpers) [Misc](#misc) [File](#file) ### Comment {{ "Comment[:2]" | doc }} {{ "ExampleComment" | example }} {{ "ExampleComment_multiline" | example }} {{ "Comment[2:]" | doc }} {{ "ExampleComment_formatting_disabled" | example }} ### Commentf {{ "Commentf[0]" | doc }} {{ "ExampleCommentf" | example }} # Helpers [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) **Helpers** [Misc](#misc) [File](#file) ### Func methods All constructs that accept a variadic list of items are paired with GroupFunc functions that accept a func(*Group). Use for embedding logic. {{ "ExampleValuesFunc" | example }} {{ "ExampleBlockFunc" | example }} ### Add {{ "Add" | doc }} {{ "ExampleAdd" | example }} {{ "ExampleAdd_var" | example }} ### Do {{ "Do" | doc }} {{ "ExampleDo" | example }} # Misc [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) **Misc** [File](#file) ### Tag {{ "Tag" | doc }} {{ "ExampleTag" | example }} Note: the items are ordered by key when rendered to ensure repeatable code. ### Null {{ "Null" | doc }} In lists, nil will produce the same effect. {{ "ExampleNull_and_nil" | example }} ### Empty {{ "Empty" | doc }} {{ "ExampleEmpty" | example }} ### Line {{ "Line" | doc }} ### Clone Be careful when passing *Statement. Consider the following... {{ "ExampleStatement_Clone_broken" | example }} Id("a") returns a *Statement, which the Call() method appends to twice. To avoid this, use Clone. {{ "Statement.Clone" | doc }} {{ "ExampleStatement_Clone_fixed" | example }} ### Cgo The cgo "C" pseudo-package is a special case, and always renders without a package alias. The import can be added with `Qual`, `Anon` or by supplying a preamble. The preamble is added with `File.CgoPreamble` which has the same semantics as [Comment](#comments). If a preamble is provided, the import is separated, and preceded by the preamble. {{ "ExampleFile_CgoPreamble" | example }} # File [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) **File** {{ "File" | doc }} ### NewFile {{ "NewFile" | doc }} ### NewFilePath {{ "NewFilePath" | doc }} ### NewFilePathName {{ "NewFilePathName" | doc }} {{ "ExampleNewFilePathName" | example }} ### Save {{ "File.Save" | doc }} ### Render {{ "File.Render" | doc }} {{ "ExampleFile_Render" | example }} ### Anon {{ "File.Anon" | doc }} {{ "ExampleFile_Anon" | example }} ### ImportName {{ "File.ImportName" | doc }} {{ "ExampleFile_ImportName" | example }} ### ImportNames {{ "File.ImportNames" | doc }} ### ImportAlias {{ "File.ImportAlias" | doc }} {{ "ExampleFile_ImportAlias" | example }} ### Comments {{ "File.PackageComment" | doc }} {{ "File.HeaderComment" | doc }} {{ "File.CanonicalPath" | doc }} {{ "ExampleFile_HeaderAndPackageComments" | example }} {{ "File.CgoPreamble" | doc }} ### PackagePrefix {{ "File.PackagePrefix" | doc }} {{ "ExampleFile_PackagePrefix" | example }}