gg

package module
v0.0.0-...-a85fe52 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 10, 2026 License: Apache-2.0 Imports: 8 Imported by: 9

README

Build Status Go dev License matrix

gg

gg is a General Golang Code Generator: A Good Game to play with Golang.

package main

import (
	"fmt"

	. "github.com/donutnomad/gg"
)

func main() {
	f := NewGroup()
	f.AddPackage("main")
	f.NewImport().
		AddPath("fmt")
	f.NewFunction("main").AddBody(
		String(`fmt.Println("%s")`, "Hello, World!"),
	)
	fmt.Println(f.String())
}

Output (after go fmt)

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

Design

gg is a general golang code generator that designed for resolving problems exists in the following tools:

  • text/template: Additional syntax, Steep learning curve, Complex logic is difficult to maintain
  • dave/jennifer: Overly abstract APIs, user need to take care about (), , everywhere.
  • kubernetes-sigs/kubebuilder: Parse data from struct tags/comments, not a general code generator.

In short, gg will provide near-native golang syntax and helpful API so play a good game with Golang. With gg, we can generate golang code more easily and understandable.

Usage

Package Name
f := Group()
f.AddPackage("main")
// package main
Imports
f := Group()
f.NewImport().
    AddPath("context").
	AddDot("math").
	AddBlank("time").
	AddAlias("x", "testing")
// import (
//      "context"
//      . "math"
//      _ "time"
//      x "testing"
// )
Function
f := Group()
f.NewFunction("hello").
    WithReceiver("v", "*World").
    AddParameter("content", "string").
    AddParameter("times", "int").
    AddResult("v", "string").
    AddBody(gg.String(`return fmt.Sprintf("say %s in %d times", content, times)`))
// func (v *World) hello(content string, times int) (v string) {
//  return fmt.Sprintf("say %s in %d times", content, times)
//}
Struct
f := Group()
f.NewStruct("World").
    AddField("x", "int64").
    AddField("y", "string")
// type World struct {
//    x int64
//    y string
//}

Acknowledgement

  • gg is inspired by dave/jennifer, I borrowed most ideas and some code from it. Nice work!

Documentation

Index

Examples

Constants

This section is empty.

Variables

S is an alias to String. TODO: can we find a new name for this?

Functions

func Array

func Array(size int, elemType any, elements ...any) *iarray

Array creates an array literal with the given size, element type and elements. elemType can be a string (e.g., "int", "string") or a Node (e.g., pkg.Type("User")). elements are the items to include in the array.

Example:

Array(3, "int", Lit(1), Lit(2), Lit(3))                 // [3]int{1, 2, 3}
Array(2, "string", Lit("a"), Lit("b"))                  // [2]string{"a", "b"}
Array(5, types.Type("User"), S("User{ID: 1}"))         // [5]types.User{User{ID: 1}}

func Call

func Call(name string) *icall

Call is used to generate a function call.

func Const

func Const() *iconst

func For

func For(judge interface{}) *ifor

func Func

func Func(name string) *ifunction

Func is an alias for Function for more concise code

func Function

func Function(name string) *ifunction

Function represent both method and function in Go.

NOTES

If `WithReceiver`, we will generate a method:

func (t test) Test()

If `WithCall`, we will generate a function call:

func Test(){}()

If `AddBody`, we will generate like a function definition without body:

func Test() {
    println("Hello, World!")
}

func If

func If(judge interface{}) *iif

func Import

func Import() *iimport

Import will start a new import group.

func Interface

func Interface(name string) *iinterface

func LineComment

func LineComment(content string, args ...interface{}) *istring

func Lit

func Lit(value interface{}) *lit

func Package

func Package(name string) *ipackage

func Return

func Return(node ...interface{}) *ireturn

func Slice

func Slice(elemType any, elements ...any) *islice

Slice creates a slice literal with the given element type and elements. elemType can be a string (e.g., "int", "string") or a Node (e.g., pkg.Type("User")). elements are the items to include in the slice.

Example:

Slice("int", Lit(1), Lit(2), Lit(3))                    // []int{1, 2, 3}
Slice("string", Lit("a"), Lit("b"))                     // []string{"a", "b"}
Slice(types.Type("User"), S("User{ID: 1}"))            // []types.User{User{ID: 1}}
Slice(types.Ptr("Config"), S("&Config{}"))             // []*types.Config{&Config{}}

func String

func String(format string, args ...interface{}) *istring

String will add a format string in NewGroup, just like fmt.Printf.

func Struct

func Struct(name string) *istruct

Struct will insert a new struct.

func Switch

func Switch(judge interface{}) *iswitch

func Type

func Type(name string, typ interface{}) *itype

func TypeAlias

func TypeAlias(name string, typ interface{}) *itype

func Value

func Value(typ any) *ivalue

Value creates a composite literal for a given type. It can be used for struct literals or custom type literals (like type aliases).

For struct literals, use AddField:

Value("User").AddField("ID", "1").AddField("Name", Lit("Alice"))
// => User{ID: 1, Name: "Alice"}

For custom types (like slice/array type aliases), use AddElement:

Value("UserList").AddElement(S("User{ID: 1}"), S("User{ID: 2}"))
// => UserList{User{ID: 1}, User{ID: 2}}

func Var

func Var() *ivar

Types

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator is the main entry point for code generation. It manages packages, imports, and provides methods for generating Go code.

func New

func New() *Generator

New will create a new generator which hold the group reference.

func (*Generator) AppendFile

func (g *Generator) AppendFile(path string) error

AppendFile will append the group after the given path. Note: This only appends the body, not package/imports.

func (*Generator) Body

func (g *Generator) Body() *Group

Body returns the body group for adding code elements. This provides direct access to the internal group for adding functions, structs, etc.

func (*Generator) Bytes

func (g *Generator) Bytes() []byte

Bytes returns the complete generated code as bytes.

func (*Generator) Imports

func (g *Generator) Imports() []string

Imports returns all registered import paths.

func (*Generator) Merge

func (g *Generator) Merge(other *Generator) *Generator

Merge merges another Generator's body and imports into this one. This is useful when multiple generators need to output to the same file. The other generator's body is appended to this generator's body. Import paths are merged, with alias conflicts resolved automatically. All PackageRef in the merged generator will be updated to use the correct aliases.

func (*Generator) NewGroup

func (g *Generator) NewGroup() (ng *Group)

func (*Generator) P

func (g *Generator) P(importPath string) *PackageRef

P returns a PackageRef for the given import path. If the package was already registered, it returns the existing reference. Otherwise, it creates a new reference with an automatically resolved alias.

Example:

types := gen.P("github.com/example/types")
other := gen.P("github.com/other/types")  // auto-aliased to "types2"
types.Type("User")  // => types.User
other.Type("User")  // => types2.User

func (*Generator) PAlias

func (g *Generator) PAlias(importPath, alias string) *PackageRef

PAlias returns a PackageRef with a specific alias. Use this when you want to control the alias name explicitly.

Example:

ctx := gen.PAlias("context", "ctx")
ctx.Type("Context")  // => ctx.Context

func (*Generator) PackageName

func (g *Generator) PackageName() string

PackageName returns the current package name.

func (*Generator) SetHeader

func (g *Generator) SetHeader(format string, args ...any) *Generator

SetHeader sets a header comment that appears before the package declaration. Typically used for "Code generated by X. DO NOT EDIT." comments.

func (*Generator) SetPackage

func (g *Generator) SetPackage(name string) *Generator

SetPackage sets the package name for the generated file.

func (*Generator) String

func (g *Generator) String() string

String returns the complete generated code as a string.

func (*Generator) Write

func (g *Generator) Write(w io.Writer)

Write will write the complete generated code into the given writer. This includes the package declaration and automatically generated imports.

func (*Generator) WriteFile

func (g *Generator) WriteFile(path string) error

WriteFile will write the complete generated code into the given path.

type Group

type Group struct {
	// contains filtered or unexported fields
}

func NewGroup

func NewGroup() *Group
Example
f := NewGroup()
f.AddPackage("main")
f.NewImport().AddPath("fmt")
f.NewFunction("main").AddBody(
	String(`fmt.Println("%s")`, "Hello, World!"),
)
fmt.Println(f.String())
Output:
package main

import "fmt"
func main(){
fmt.Println("Hello, World!")}

func NewInlineGroup

func NewInlineGroup() *Group

NewInlineGroup creates a group with no separators between elements. Use this when you need to combine multiple nodes into a single line.

Example:

gg.NewInlineGroup().Append(
    gg.S("tn := "),
    gsqlPkg.Call("TableName", gg.Lit("tableName")),
)
// => tn := gsqlPkg.TableName("tableName")

func (*Group) AddLine

func (g *Group) AddLine() *Group

func (*Group) AddLineComment

func (g *Group) AddLineComment(content string, args ...interface{}) *Group

func (*Group) AddPackage

func (g *Group) AddPackage(name string) *Group

func (*Group) AddString

func (g *Group) AddString(content string, args ...interface{}) *Group

func (*Group) AddType

func (g *Group) AddType(name string, typ interface{}) *Group

func (*Group) AddTypeAlias

func (g *Group) AddTypeAlias(name string, typ interface{}) *Group

func (*Group) Append

func (g *Group) Append(node ...any) *Group

Append adds nodes to the group

func (*Group) AppendFile deprecated

func (g *Group) AppendFile(path string) error

Deprecated: use `Generator.AppendFile(w)` instead.

func (*Group) NewConst

func (g *Group) NewConst() *iconst

func (*Group) NewFor

func (g *Group) NewFor(judge interface{}) *ifor

func (*Group) NewFunction

func (g *Group) NewFunction(name string) *ifunction

func (*Group) NewIf

func (g *Group) NewIf(judge interface{}) *iif

func (*Group) NewImport

func (g *Group) NewImport() *iimport

func (*Group) NewInterface

func (g *Group) NewInterface(name string) *iinterface

func (*Group) NewStruct

func (g *Group) NewStruct(name string) *istruct

func (*Group) NewSwitch

func (g *Group) NewSwitch(judge interface{}) *iswitch

func (*Group) NewVar

func (g *Group) NewVar() *ivar

func (*Group) String

func (g *Group) String() string

func (*Group) Write deprecated

func (g *Group) Write(w io.Writer)

Deprecated: use `Generator.Write(w)` instead.

func (*Group) WriteFile deprecated

func (g *Group) WriteFile(path string) error

Deprecated: use `Generator.WriteFile(w)` instead.

type Node

type Node interface {
	// contains filtered or unexported methods
}

func Continue

func Continue() Node

func Defer

func Defer(body interface{}) Node

func Embed

func Embed(fn func() Node) Node

Embed accept a close clause to build a node.

func Line

func Line() Node

func Template

func Template(data interface{}, tmpl string) Node

type PackageRef

type PackageRef struct {
	// contains filtered or unexported fields
}

PackageRef represents a reference to an external package. It provides methods to generate qualified identifiers and automatically manages import aliases to avoid conflicts.

func (*PackageRef) Alias

func (p *PackageRef) Alias() string

Alias returns the resolved alias for this package.

func (*PackageRef) Call

func (p *PackageRef) Call(name string, args ...any) *icall

Call returns a qualified function call. Example: types.NewUser("name")

func (*PackageRef) Chan

func (p *PackageRef) Chan(name string) Node

Chan returns a channel type of the given type name. Example: chan types.Event

func (*PackageRef) ChanRecv

func (p *PackageRef) ChanRecv(name string) Node

ChanRecv returns a receive-only channel type. Example: <-chan types.Event

func (*PackageRef) ChanSend

func (p *PackageRef) ChanSend(name string) Node

ChanSend returns a send-only channel type. Example: chan<- types.Event

func (*PackageRef) Dot

func (p *PackageRef) Dot(name string) Node

Dot returns a qualified identifier node (for constants, variables, etc.). Example: types.DefaultTimeout

func (*PackageRef) Func

func (p *PackageRef) Func(name string) Node

Func returns a qualified function reference (without calling it). Example: types.ParseConfig

func (*PackageRef) Generic

func (p *PackageRef) Generic(name string, typeArgs ...any) Node

Generic returns a generic type instantiation. Example:

types.Generic("List", "string")              // types.List[string]
types.Generic("Map", "string", types.Type("User")) // types.Map[string, types.User]

func (*PackageRef) ImportPath

func (p *PackageRef) ImportPath() string

ImportPath returns the full import path of the package.

func (*PackageRef) Map

func (p *PackageRef) Map(keyType any, valueType any) Node

Map returns a map type with the given key and value types. Both key and value can be: string (type name), Node, or *PackageRef method result. Example:

types.Map("string", "User")           // map[string]types.User
types.Map(other.Type("Key"), "Value") // map[other.Key]types.Value
Map(types.Type("Key"), types.Type("Value")) // map[types.Key]types.Value (use package-level Map)

func (*PackageRef) Ptr

func (p *PackageRef) Ptr(name string) Node

Ptr returns a pointer type of the given type name. Example: *types.User

func (*PackageRef) Slice

func (p *PackageRef) Slice(name string) Node

Slice returns a slice type of the given type name. Example: []types.User

func (*PackageRef) Type

func (p *PackageRef) Type(name string) Node

Type returns a qualified type name node. Example: types.User

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL