jennifer

jennifer

简洁灵活的Go代码生成库

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

Jennifer代码生成Go语言DSL开源库Github开源项目

文档 稳定性-稳定

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以禁用生成的源代码的格式化。当性能至关重要且不需要可读性高的代码时,这可能会很有用。

编辑推荐精选

博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

热门AI工具AI办公办公工具智能排版AI生成PPT博思AIPPT海量精品模板AI创作
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

AI助手热门AI工具AI创作AI辅助写作讯飞绘文内容运营个性化文章多平台分发
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

热门AI工具生产力协作转型TraeAI IDE
商汤小浣熊

商汤小浣熊

最强AI数据分析助手

小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。

imini AI

imini AI

像人一样思考的AI智能体

imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。

下拉加载更多