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

编辑推荐精选

Vora

Vora

免费创建高清无水印Sora视频

Vora是一个免费创建高清无水印Sora视频的AI工具

Refly.AI

Refly.AI

最适合小白的AI自动化工作流平台

无需编码,轻松生成可复用、可变现的AI自动化工作流

酷表ChatExcel

酷表ChatExcel

大模型驱动的Excel数据处理工具

基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。

AI工具酷表ChatExcelAI智能客服AI营销产品使用教程
TRAE编程

TRAE编程

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

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

AI工具TraeAI IDE协作生产力转型热门
AIWritePaper论文写作

AIWritePaper论文写作

AI论文写作指导平台

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

AI辅助写作AI工具AI论文工具论文写作智能生成大纲数据安全AI助手热门
博思AIPPT

博思AIPPT

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

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

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

潮际好麦

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

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

iTerms

iTerms

企业专属的AI法律顾问

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

SimilarWeb流量提升

SimilarWeb流量提升

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

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

Sora2视频免费生成

Sora2视频免费生成

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

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

下拉加载更多