Jennifer
Jennifer is a code generator for Go
Install / Use
/learn @dave/JenniferREADME
Jennifer
Jennifer is a code generator for Go.
package main
import (
"fmt"
. "github.com/dave/jennifer/jen"
)
func main() {
f := NewFile("main")
f.Func().Id("main").Params().Block(
Qual("fmt", "Println").Call(Lit("Hello, world")),
)
fmt.Printf("%#v", f)
}
Output:
package main
import "fmt"
func main() {
fmt.Println("Hello, world")
}
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 for an index. Here's some examples of jennifer being used in the real-world:
- genjen (which generates much of jennifer, using data in data.go)
- zerogen
- go-contentful-generator
Rendering
For testing, a File or Statement can be rendered with the fmt package using the %#v verb.
c := Id("a").Call(Lit("b"))
fmt.Printf("%#v", c)
// Output:
// a("b")
This is not recommended for use in production because any error will cause a panic. For production use, File.Render or File.Save are preferred.
Identifiers
Identifiers Keywords Operators Braces Parentheses Control flow Collections Literals Comments Generics Helpers Misc File
Id
Id renders an identifier.
c := If(Id("i").Op("==").Id("j")).Block(
Return(Id("i")),
)
fmt.Printf("%#v", c)
// Output:
// if i == j {
// return i
// }
Dot
Dot renders a period followed by an identifier. Use for fields and selectors.
c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz")
fmt.Printf("%#v", c)
// Output:
// c.Foo().Bar[0].Baz
Qual
Qual renders a qualified identifier.
c := Qual("encoding/gob", "NewEncoder").Call()
fmt.Printf("%#v", c)
// Output:
// gob.NewEncoder()
Imports are automatically added when used with a File. If the path matches the local path, the package name is omitted. If package names conflict they are automatically renamed.
f := NewFilePath("a.b/c")
f.Func().Id("init").Params().Block(
Qual("a.b/c", "Foo").Call().Comment("Local package - name is omitted."),
Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."),
Qual("g.h/f", "Baz").Call().Comment("Colliding package name is renamed."),
)
fmt.Printf("%#v", f)
// Output:
// package c
//
// import (
// f "d.e/f"
// f1 "g.h/f"
// )
//
// func init() {
// Foo() // Local package - name is omitted.
// f.Bar() // Import is automatically added.
// f1.Baz() // Colliding package name is renamed.
// }
Note that it is not possible to reliably determine the package name given an arbitrary package path, so a sensible name is guessed from the path and added as an alias. The names of all standard library packages are known so these do not need to be aliased. If more control is needed of the aliases, see File.ImportName or File.ImportAlias.
List
List renders a comma separated list. Use for multiple return functions.
c := List(Id("a"), Err()).Op(":=").Id("b").Call()
fmt.Printf("%#v", c)
// Output:
// a, err := b()
Keywords
Identifiers Keywords Operators Braces Parentheses Control flow Collections Literals Comments Generics Helpers Misc 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, Clear, Close, Complex, Copy, Delete, Imag, Len, Make, Max, Min, 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:
c := Id("a").Op("=").Append(Id("a"), Id("b").Op("..."))
fmt.Printf("%#v", c)
// Output:
// a = append(a, b...)
Special cases for If, For, Interface, Struct, Switch, Case, Return and Map are explained below.
Operators
Identifiers Keywords Operators Braces Parentheses Control flow Collections Literals Comments Generics Helpers Misc File
Op renders the provided operator / token.
c := Id("a").Op(":=").Id("b").Call()
fmt.Printf("%#v", c)
// Output:
// a := b()
c := Id("a").Op("=").Op("*").Id("b")
fmt.Printf("%#v", c)
// Output:
// a = *b
c := Id("a").Call(Id("b").Op("..."))
fmt.Printf("%#v", c)
// Output:
// a(b...)
c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block()
fmt.Printf("%#v", c)
// Output:
// if (a || b) && c {
// }
Braces
Identifiers Keywords Operators Braces Parentheses Control flow Collections Literals Comments Generics Helpers Misc File
Several methods render curly braces, summarized below:
| Name | Prefix | Separator | Example |
| ------------------------------ | ------------ | --------- | -------------------------------------|
| Block | | \n | func a() { ... } or if a { ... } |
| Interface | interface | \n | interface { ... } |
| Struct | struct | \n | struct { ... } |
| Values | | , | []int{1, 2} or A{B: "c"} |
Block
Block renders a statement list enclosed by curly braces. Use for code blocks.
c := Func().Id("foo").Params().String().Block(
Id("a").Op("=").Id("b"),
Id("b").Op("++"),
Return(Id("b")),
)
fmt.Printf("%#v", c)
// Output:
// func foo() string {
// a = b
// b++
// return b
// }
c := If(Id("a").Op(">").Lit(10)).Block(
Id("a").Op("=").Id("a").Op("/").Lit(2),
)
fmt.Printf("%#v", c)
// Output:
// if a > 10 {
// a = a / 2
// }
A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. See example.
Interface, Struct
Interface and Struct render the keyword followed by a statement list enclosed by curly braces.
c := Var().Id("a").Interface()
fmt.Printf("%#v", c)
// Output:
// var a interface{}
c := Type().Id("a").Interface(
Id("b").Params().String(),
)
fmt.Printf("%#v", c)
// Output:
// type a interface {
// b() string
// }
c := Id("c").Op(":=").Make(Chan().Struct())
fmt.Printf("%#v", c)
// Output:
// c := make(chan struct{})
c := Type().Id("foo").Struct(
List(Id("x"), Id("y")).Int(),
Id("u").Float32(),
)
fmt.Printf("%#v", c)
// Output:
// type foo struct {
// x, y int
// u float32
// }
Parentheses
Identifiers Keywords Operators Braces Parentheses Control flow Collections Literals Comments Generics Helpers Misc File
Several methods output parenthesis, summarized below:
| Name | Prefix | Separator | Example |
| ----------------- | ------ | --------- | --------------------------------- |
| Call | | , | fmt.Println(b, c) |
| Params | | , | func (a *A) Foo(i int) { ... } |
| Defs | | \n | const ( ... ) |
| Parens | | | []byte(s) or a / (b + c) |
| Assert | . | | s, ok := i.(string) |
Call
Call renders a comma separated list enclosed by parenthesis. Use for function calls.
c := Qual("fmt", "Printf").Call(
Lit("%#v: %T\n"),
Id("a"),
Id("b"),
)
fmt.Printf("%#v", c)
// Output:
// fmt.Printf("%#v: %T\n", a, b)
Params
Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers.
c := Func().Params(
Id("a").Id("A"),
).Id("foo").Params(
Id("b"),
Id("c").String(),
).String().Block(
Return(Id("b").Op("+").Id("c")),
)
fmt.Printf("%#v", c)
// Output:
// func (a A) foo(b, c string) string {
// return b + c
// }
Defs
Defs renders a statement list enclosed in parenthesis. Use for definition lists.
c := Const().Defs(
Id("a").Op("=").Lit("a"),
Id("b").Op("=").Lit("b"),
)
fmt.Printf("%#v", c)
// Output:
// const (
// a = "a"
// b = "b"
// )
Parens
Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order
Related Skills
node-connect
347.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
347.2kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
108.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
