Project Icon

jennifer

简洁灵活的Go代码生成库

Jennifer是一个Go语言代码生成库,提供简洁API用于生成各种Go语法结构。它支持自动导入包、生成函数、接口和结构体等。Jennifer适用于自动化代码生成任务,可提高开发效率。该库的灵活性使开发者能够创建复杂的代码模板,适合多种代码生成场景。

文档 稳定性-稳定

Jennifer

Jennifer 是一个 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)
}

输出:

package main

import "fmt"

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

安装

go get -u github.com/dave/jennifer/jen

需要帮助?

如果你遇到困难,有问题,想要代码审查,或只是想聊聊:我很乐意帮忙!随时可以开一个 issue,给我发邮件,或在你的 PR 中提到 @dave。

示例

Jennifer 有一套全面的示例 - 请查看 godoc 索引。以下是一些 Jennifer 在实际项目中使用的例子:

渲染

对于测试,可以使用 fmt 包的 %#v 动词渲染 File 或 Statement。

c := Id("a").Call(Lit("b"))
fmt.Printf("%#v", c)
// 输出:
// a("b")

不建议在生产环境中使用这种方式,因为任何错误都会导致 panic。对于生产环境,推荐使用 File.RenderFile.Save

标识符

标识符 关键字 运算符 括号 圆括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

Id

Id 渲染一个标识符。

c := If(Id("i").Op("==").Id("j")).Block(
	Return(Id("i")),
)
fmt.Printf("%#v", c)
// 输出:
// if i == j {
// 	return i
// }

Dot

Dot 渲染一个句点后跟一个标识符。用于字段和选择器。

c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz")
fmt.Printf("%#v", c)
// 输出:
// c.Foo().Bar[0].Baz

Qual

Qual 渲染一个限定标识符。

c := Qual("encoding/gob", "NewEncoder").Call()
fmt.Printf("%#v", c)
// 输出:
// gob.NewEncoder()

当与 File 一起使用时,会自动添加导入。如果路径与本地路径匹配,则省略包名。如果包名冲突,会自动重命名。

f := NewFilePath("a.b/c")
f.Func().Id("init").Params().Block(
	Qual("a.b/c", "Foo").Call().Comment("本地包 - 省略包名。"),
	Qual("d.e/f", "Bar").Call().Comment("自动添加导入。"),
	Qual("g.h/f", "Baz").Call().Comment("冲突的包名会被重命名。"),
)
fmt.Printf("%#v", f)
// 输出:
// package c
//
// import (
// 	f "d.e/f"
// 	f1 "g.h/f"
// )
//
// func init() {
// 	Foo()    // 本地包 - 省略包名。
// 	f.Bar()  // 自动添加导入。
// 	f1.Baz() // 冲突的包名会被重命名。
// }

注意,无法可靠地根据任意包路径确定包名,所以会根据路径猜测一个合理的名称并添加为别名。所有标准库包的名称都是已知的,因此不需要别名。如果需要更多地控制别名,请参见 File.ImportNameFile.ImportAlias

List

List 渲染一个逗号分隔的列表。用于多返回值函数。

c := List(Id("a"), Err()).Op(":=").Id("b").Call()
fmt.Printf("%#v", c)
// 输出:
// a, err := b()

关键字

标识符 关键字 运算符 括号 圆括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

简单的关键字、预声明标识符和内置函数都是不言自明的:

构造名称
关键字Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var
函数Append, Cap, Clear, Close, Complex, Copy, Delete, Imag, Len, Make, Max, Min, New, Panic, Print, Println, Real, Recover
类型Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr
常量True, False, Iota, Nil
辅助函数Err

内置函数接受一个参数列表并适当地渲染它们:

c := Id("a").Op("=").Append(Id("a"), Id("b").Op("..."))
fmt.Printf("%#v", c)
// 输出:
// a = append(a, b...)

If, ForInterface, StructSwitch, CaseReturnMap 的特殊情况将在下面解释。

运算符

标识符 关键字 运算符 括号 圆括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

Op 渲染提供的运算符/标记。

c := Id("a").Op(":=").Id("b").Call()
fmt.Printf("%#v", c)
// 输出:
// a := b()
c := Id("a").Op("=").Op("*").Id("b")
fmt.Printf("%#v", c)
// 输出:
// a = *b
c := Id("a").Call(Id("b").Op("..."))
fmt.Printf("%#v", c)
// 输出:
// a(b...)
c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block()
fmt.Printf("%#v", c)
// 输出:
// if (a || b) && c {
// }

大括号

标识符 关键字 运算符 大括号 小括号 流程控制 集合 字面量 注释 泛型 辅助函数 其他 文件

以下几种方法用于渲染大括号,总结如下:

名称前缀分隔符示例
Block\nfunc a() { ... }if a { ... }
Interfaceinterface\ninterface { ... }
Structstruct\nstruct { ... }
Values,[]int{1, 2}A{B: "c"}

Block

Block 渲染由大括号括起来的语句列表。用于代码块。

c := Func().Id("foo").Params().String().Block(
	Id("a").Op("=").Id("b"),
	Id("b").Op("++"),
	Return(Id("b")),
)
fmt.Printf("%#v", c)
// 输出:
// 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)
// 输出:
// if a > 10 {
// 	a = a / 2
// }

在 Case 或 Default 后直接使用时有一个特殊情况,此时会省略大括号。这允许在 switch 和 select 语句中使用。参见示例

Interface, Struct

Interface 和 Struct 渲染关键字后跟由大括号括起来的语句列表。

c := Var().Id("a").Interface()
fmt.Printf("%#v", c)
// 输出:
// var a interface{}
c := Type().Id("a").Interface(
	Id("b").Params().String(),
)
fmt.Printf("%#v", c)
// 输出:
// type a interface {
// 	b() string
// }
c := Id("c").Op(":=").Make(Chan().Struct())
fmt.Printf("%#v", c)
// 输出:
// c := make(chan struct{})
c := Type().Id("foo").Struct(
	List(Id("x"), Id("y")).Int(),
	Id("u").Float32(),
)
fmt.Printf("%#v", c)
// 输出:
// type foo struct {
// 	x, y int
// 	u    float32
// }

小括号

标识符 关键字 运算符 大括号 小括号 流程控制 集合 字面量 注释 泛型 辅助函数 其他 文件

几种方法输出小括号,总结如下:

名称前缀分隔符示例
Call,fmt.Println(b, c)
Params,func (a *A) Foo(i int) { ... }
Defs\nconst ( ... )
Parens[]byte(s)a / (b + c)
Assert.s, ok := i.(string)

Call

Call 渲染由小括号括起来的逗号分隔列表。用于函数调用。

c := Qual("fmt", "Printf").Call(
	Lit("%#v: %T\n"),
	Id("a"),
	Id("b"),
)
fmt.Printf("%#v", c)
// 输出:
// fmt.Printf("%#v: %T\n", a, b)

Params

Params 渲染由小括号括起来的逗号分隔列表。用于函数参数和方法接收器。

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)
// 输出:
// func (a A) foo(b, c string) string {
// 	return b + c
// }

Defs

Defs 渲染由小括号括起来的语句列表。用于定义列表。

c := Const().Defs(
	Id("a").Op("=").Lit("a"),
	Id("b").Op("=").Lit("b"),
)
fmt.Printf("%#v", c)
// 输出:
// const (
// 	a = "a"
// 	b = "b"
// )

Parens

Parens 在小括号中渲染单个项目。用于类型转换或指定求值顺序。

c := Id("b").Op(":=").Index().Byte().Parens(Id("s"))
fmt.Printf("%#v", c)
// 输出:
// b := []byte(s)
c := Id("a").Op("/").Parens(Id("b").Op("+").Id("c"))
fmt.Printf("%#v", c)
// 输出:
// a / (b + c)

Assert

Assert 渲染一个句点后跟由小括号括起来的单个项目。用于类型断言。

c := List(Id("b"), Id("ok")).Op(":=").Id("a").Assert(Bool())
fmt.Printf("%#v", c)
// 输出:
// b, ok := a.(bool)

流程控制

标识符 关键字 运算符 大括号 小括号 流程控制 集合 字面量 注释 泛型 辅助函数 其他 文件

If, For

If 和 For 渲染关键字后跟分号分隔的列表。

c := If(
	Err().Op(":=").Id("a").Call(),
	Err().Op("!=").Nil(),
).Block(
	Return(Err()),
)
fmt.Printf("%#v", c)
// 输出:
// if err := a(); err != nil {
// 	return err
// }
c := For(
	Id("i").Op(":=").Lit(0),
	Id("i").Op("<").Lit(10),
	Id("i").Op("++"),
).Block(
	Qual("fmt", "Println").Call(Id("i")),
)
fmt.Printf("%#v", c)
// 输出:
// for i := 0; i < 10; i++ {
// 	fmt.Println(i)
// }

Switch, Select

Switch、Select、Case和Block用于构建switch或select语句:

c := Switch(Id("value").Dot("Kind").Call()).Block(
	Case(Qual("reflect", "Float32"), Qual("reflect", "Float64")).Block(
		Return(Lit("float")),
	),
	Case(Qual("reflect", "Bool")).Block(
		Return(Lit("bool")),
	),
	Case(Qual("reflect", "Uintptr")).Block(
		Fallthrough(),
	),
	Default().Block(
		Return(Lit("none")),
	),
)
fmt.Printf("%#v", c)
// 输出:
// switch value.Kind() {
// case reflect.Float32, reflect.Float64:
// 	return "float"
// case reflect.Bool:
// 	return "bool"
// case reflect.Uintptr:
// 	fallthrough
// default:
// 	return "none"
// }

Return

Return渲染关键字,后跟逗号分隔的列表。

c := Return(Id("a"), Id("b"))
fmt.Printf("%#v", c)
// 输出:
// return a, b

集合

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

Map

Map渲染关键字,后跟一个由方括号括起来的单个项目。用于map定义。

c := Id("a").Op(":=").Map(String()).String().Values()
fmt.Printf("%#v", c)
// 输出:
// a := map[string]string{}

Index

Index渲染由方括号括起来的冒号分隔列表。用于数组/切片索引和定义。

c := Var().Id("a").Index().String()
fmt.Printf("%#v", c)
// 输出:
// var a []string
c := Id("a").Op(":=").Id("b").Index(Lit(0), Lit(1))
fmt.Printf("%#v", c)
// 输出:
// a := b[0:1]
c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty())
fmt.Printf("%#v", c)
// 输出:
// a := b[1:]

Values

Values渲染由大括号括起来的逗号分隔列表。用于切片或复合字面量。

c := Index().String().Values(Lit("a"), Lit("b"))
fmt.Printf("%#v", c)
// 输出:
// []string{"a", "b"}

Dict渲染为键/值对。与Values一起用于map或复合字面量。

c := Map(String()).String().Values(Dict{
	Lit("a"):	Lit("b"),
	Lit("c"):	Lit("d"),
})
fmt.Printf("%#v", c)
// 输出:
// map[string]string{
// 	"a": "b",
// 	"c": "d",
// }
c := Op("&").Id("Person").Values(Dict{
	Id("Age"):	Lit(1),
	Id("Name"):	Lit("a"),
})
fmt.Printf("%#v", c)
// 输出:
// &Person{
// 	Age:  1,
// 	Name: "a",
// }

DictFunc执行func(Dict)来生成值。

c := Id("a").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) {
	d[Lit("a")] = Lit("b")
	d[Lit("c")] = Lit("d")
}))
fmt.Printf("%#v", c)
// 输出:
// a := map[string]string{
// 	"a": "b",
// 	"c": "d",
// }

注意:渲染时项目按键排序,以确保生成的代码可重复。

字面量

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

Lit

Lit渲染字面量。Lit只支持内置类型(bool、string、int、complex128、float64、float32、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、uintptr和complex64)。 传递任何其他类型都会引发panic。

c := Id("a").Op(":=").Lit("a")
fmt.Printf("%#v", c)
// 输出:
// a := "a"
c := Id("a").Op(":=").Lit(1.5)
fmt.Printf("%#v", c)
// 输出:
// a := 1.5

LitFunc通过执行提供的函数来生成要渲染的值。

c := Id("a").Op(":=").LitFunc(func() interface{} { return 1 + 1 })
fmt.Printf("%#v", c)
// 输出:
// a := 2

对于默认常量类型(bool、int、float64、string、complex128),Lit 将渲染无类型常量。

代码输出
Lit(true)true
Lit(1)1
Lit(1.0)1.0
Lit("foo")"foo"
Lit(0 + 1i)(0 + 1i)

对于所有其他内置类型(float32、int8、int16、int32、int64、uint、uint8、 uint16、uint32、uint64、uintptr、complex64),Lit也会渲染类型。

代码输出
Lit(float32(1))float32(1)
Lit(int16(1))int16(1)
Lit(uint8(0x1))uint8(0x1)
Lit(complex64(0 + 1i))complex64(0 + 1i)

内置别名类型byte和rune需要特殊处理。LitRune和LitByte 渲染rune和byte字面量。

代码输出
LitRune('x')'x'
LitByte(byte(0x1))byte(0x1)

注释

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 杂项 文件

Comment

Comment 添加一条注释。如果提供的字符串包含换行符,注释将以多行样式格式化。

f := NewFile("a")
f.Comment("Foo 返回字符串 \"foo\"")
f.Func().Id("Foo").Params().String().Block(
	Return(Lit("foo")).Comment("返回字符串 foo"),
)
fmt.Printf("%#v", f)
// 输出:
// package a
//
// // Foo 返回字符串 "foo"
// func Foo() string {
// 	return "foo" // 返回字符串 foo
// }
c := Comment("a\nb")
fmt.Printf("%#v", c)
// 输出:
// /*
// a
// b
// */

如果注释字符串以 "//" 或 "/*" 开头,自动格式化将被禁用,字符串将直接渲染。

c := Id("foo").Call(Comment("/* 内联 */")).Comment("//无空格")
fmt.Printf("%#v", c)
// 输出:
// foo( /* 内联 */ ) //无空格

Commentf

Commentf 使用格式字符串和参数列表添加注释。

name := "foo"
val := "bar"
c := Id(name).Op(":=").Lit(val).Commentf("%s 是字符串 \"%s\"", name, val)
fmt.Printf("%#v", c)
// 输出:
// foo := "bar" // foo 是字符串 "bar"

泛型

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 杂项 文件

希望随着 Go 1.18 引入泛型,生成代码的需求会减少。然而,为了完整性,我们现在支持泛型,包括 anycomparable 预声明标识符,以及 TypesUnion 列表。要生成近似(~)标记,请使用 Op("~")

Types

Types 渲染一个用方括号括起来的逗号分隔列表。用于类型参数和约束。

Union

Union 渲染一个用管道符分隔的列表。用于联合类型约束。

示例

c := Func().Id("Keys").Types(
	Id("K").Comparable(),
	Id("V").Any(),
).Params(
	Id("m").Map(Id("K")).Id("V"),
).Index().Id("K").Block()
fmt.Printf("%#v", c)
// 输出:
// func Keys[K comparable, V any](m map[K]V) []K {}
c := Return(Id("Keys").Types(Int(), String()).Call(Id("m")))
fmt.Printf("%#v", c)
// 输出:
// return Keys[int, string](m)
c := Type().Id("PredeclaredSignedInteger").Interface(
	Union(Int(), Int8(), Int16(), Int32(), Int64()),
)
fmt.Printf("%#v", c)
// 输出:
// type PredeclaredSignedInteger interface {
//	int | int8 | int16 | int32 | int64
// }
c := Type().Id("AnyString").Interface(
	Op("~").String(),
)
fmt.Printf("%#v", c)
// 输出:
// type AnyString interface {
//	~string
// }

辅助函数

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 杂项 文件

Func 方法

所有接受可变参数列表的构造都配对有 GroupFunc 函数,这些函数接受一个 func(*Group)。用于嵌入逻辑。

c := Id("numbers").Op(":=").Index().Int().ValuesFunc(func(g *Group) {
	for i := 0; i <= 5; i++ {
		g.Lit(i)
	}
})
fmt.Printf("%#v", c)
// 输出:
// numbers := []int{0, 1, 2, 3, 4, 5}
increment := true
name := "a"
c := Func().Id("a").Params().BlockFunc(func(g *Group) {
	g.Id(name).Op("=").Lit(1)
	if increment {
		g.Id(name).Op("++")
	} else {
		g.Id(name).Op("--")
	}
})
fmt.Printf("%#v", c)
// 输出:
// func a() {
// 	a = 1
// 	a++
// }

Add

Add 将提供的项添加到语句中。

ptr := Op("*")
c := Id("a").Op("=").Add(ptr).Id("b")
fmt.Printf("%#v", c)
// 输出:
// a = *b
a := Id("a")
i := Int()
c := Var().Add(a, i)
fmt.Printf("%#v", c)
// 输出:
// var a int

Do

Do 使用语句作为参数调用提供的函数。用于嵌入逻辑。

f := func(name string, isMap bool) *Statement {
	return Id(name).Op(":=").Do(func(s *Statement) {
		if isMap {
			s.Map(String()).String()
		} else {
			s.Index().String()
		}
	}).Values()
}
fmt.Printf("%#v\n%#v", f("a", true), f("b", false))
// 输出:
// a := map[string]string{}
// b := []string{}

杂项

标识符 关键字 运算符 大括号 小括号 控制流 集合 字面量 注释 泛型 辅助函数 杂项 文件

Tag

Tag 渲染一个结构体标签

c := Type().Id("foo").Struct(
	Id("A").String().Tag(map[string]string{"json": "a"}),
	Id("B").Int().Tag(map[string]string{"json": "b", "bar": "baz"}),
)
fmt.Printf("%#v", c)
// 输出:
// type foo struct {
// 	A string `json:"a"`
// 	B int    `bar:"baz" json:"b"`
// }

注意:渲染时项目按键排序,以确保代码可重复。

Null

Null 添加一个空项。空项不渲染任何内容,在列表中也不会跟随分隔符。

在列表中,nil 将产生相同的效果。

c := Func().Id("foo").Params(
	nil,
	Id("s").String(),
	Null(),
	Id("i").Int(),
).Block()
fmt.Printf("%#v", c)
// 输出:
// func foo(s string, i int) {}

Empty

Empty 添加一个空项。空项不会渲染任何内容,但在列表中会跟随一个分隔符。

c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty())
fmt.Printf("%#v", c)
// 输出:
// a := b[1:]

Line

Line 插入一个空行。

Clone

使用 *Statement 时要小心。考虑以下情况...

a := Id("a")
c := Block(
	a.Call(),
	a.Call(),
)
fmt.Printf("%#v", c)
// 输出:
// {
// 	a()()
// 	a()()
// }

Id("a") 返回一个 *Statement,Call() 方法会对其进行两次追加。为避免这种情况,使用 Clone。Clone 会复制 Statement,这样可以追加更多的标记而不影响原始语句。

a := Id("a")
c := Block(
	a.Clone().Call(),
	a.Clone().Call(),
)
fmt.Printf("%#v", c)
// 输出:
// {
// 	a()
// 	a()
// }

Cgo

cgo 的 "C" 伪包是一个特殊情况,它总是渲染时不带包别名。可以使用 QualAnon 或提供前言来添加导入。前言可以通过 File.CgoPreamble 添加,其语义与 Comment 相同。如果提供了前言,导入会被分开,并在前言之后。

f := NewFile("a")
f.CgoPreamble(`#include <stdio.h>
#include <stdlib.h>

void myprint(char* s) {
printf("%s\n", s);
}
`)
f.Func().Id("init").Params().Block(
	Id("cs").Op(":=").Qual("C", "CString").Call(Lit("Hello from stdio\n")),
	Qual("C", "myprint").Call(Id("cs")),
	Qual("C", "free").Call(Qual("unsafe", "Pointer").Parens(Id("cs"))),
)
fmt.Printf("%#v", f)
// 输出:
// package a
//
// import "unsafe"
//
// /*
// #include <stdio.h>
// #include <stdlib.h>
//
// void myprint(char* s) {
// 	printf("%s\n", s);
// }
// */
// import "C"
//
// func init() {
// 	cs := C.CString("Hello from stdio\n")
// 	C.myprint(cs)
// 	C.free(unsafe.Pointer(cs))
// }

File

标识符 关键字 操作符 花括号 圆括号 控制流 集合 字面量 注释 泛型 辅助函数 其他 文件

File 代表一个单独的源文件。包导入由 File 自动管理。

NewFile

NewFile 创建一个新文件,指定包名。

NewFilePath

NewFilePath 创建一个新文件,同时指定包路径 - 包名从路径中推断。

NewFilePathName

NewFilePathName 创建一个新文件,指定包路径和名称。

f := NewFilePathName("a.b/c", "main")
f.Func().Id("main").Params().Block(
	Qual("a.b/c", "Foo").Call(),
)
fmt.Printf("%#v", f)
// 输出:
// package main
//
// func main() {
// 	Foo()
// }

Save

Save 渲染文件并保存到指定的文件名。

Render

Render 将文件渲染到提供的 writer。

f := NewFile("a")
f.Func().Id("main").Params().Block()
buf := &bytes.Buffer{}
err := f.Render(buf)
if err != nil {
	fmt.Println(err.Error())
} else {
	fmt.Println(buf.String())
}
// 输出:
// package a
//
// func main() {}

Anon

Anon 添加一个匿名导入。

f := NewFile("c")
f.Anon("a")
f.Func().Id("init").Params().Block()
fmt.Printf("%#v", f)
// 输出:
// package c
//
// import _ "a"
//
// func init() {}

ImportName

ImportName 为路径提供包名。如果指定,别名将从导入块中省略。这是可选的。如果未指定,将根据路径使用一个合理的包名,并将其作为别名添加到导入块中。

f := NewFile("main")

// 包 a 应使用名称 "a"
f.ImportName("github.com/foo/a", "a")

// 包 b 在代码中未使用,因此不会被包含
f.ImportName("github.com/foo/b", "b")

f.Func().Id("main").Params().Block(
	Qual("github.com/foo/a", "A").Call(),
)
fmt.Printf("%#v", f)

// 输出:
// package main
//
// import "github.com/foo/a"
//
// func main() {
// 	a.A()
// }

ImportNames

ImportNames 允许以映射的形式导入多个名称。使用 gennames 命令可以自动生成一个包含选定包名映射的 go 文件。

ImportAlias

ImportAlias 为包路径提供在导入块中应使用的别名。可以使用句点强制点导入。

f := NewFile("main")

// 包 a 应别名为 "b"
f.ImportAlias("github.com/foo/a", "b")

// 包 c 在代码中未使用,因此不会被包含
f.ImportAlias("github.com/foo/c", "c")

f.Func().Id("main").Params().Block(
	Qual("github.com/foo/a", "A").Call(),
)
fmt.Printf("%#v", f)

// 输出:
// package main
//
// import b "github.com/foo/a"
//
// func main() {
// 	b.A()
// }

Comments

PackageComment 在文件顶部、包关键字上方添加注释。

HeaderComment 在文件顶部、任何包注释上方添加注释。在头部注释下方会渲染一个空行,确保头部注释不包含在包文档中。

CanonicalPath 向包子句添加规范导入路径注释。

f := NewFile("c")
f.CanonicalPath = "d.e/f"
f.HeaderComment("代码由...生成")
f.PackageComment("包 c 实现了...")
f.Func().Id("init").Params().Block()
fmt.Printf("%#v", f)
// 输出:
// // 代码由...生成
//
// // 包 c 实现了...
// package c // import "d.e/f"
//
// func init() {}

CgoPreamble 添加一个 cgo 前言注释,直接在 "C" 伪包导入之前渲染。

PackagePrefix

如果你担心生成的包别名与本地变量名冲突,可以在这里设置前缀。包 foo 变成 {prefix}_foo。

f := NewFile("a")
f.PackagePrefix = "pkg"
f.Func().Id("main").Params().Block(
	Qual("b.c/d", "E").Call(),
)
fmt.Printf("%#v", f)
// 输出:
// package a
//
// import pkg_d "b.c/d"
//
// func main() {
// 	pkg_d.E()
// }

NoFormat

可以将NoFormat设置为true以禁用生成的源代码的格式化。当性能至关重要且不需要可读性高的代码时,这可能会很有用。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号