我很难理解go generate
。我也发现几乎没有关于go generate
的帖子。
请在以下示例中解释go generate
:
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// --- Address
type Address struct {
Id bson.ObjectId `bson:"_id,omitempty"`
AccountId string `bson:"account_id"`
Name string `bson:"name"`
StreetAddress string `bson:"streetaddress"`
Town string `bson:"town"`
Country string `bson:"country"`
}
// --- AddressHandler
type AddressHandler struct {
MS *mgo.Session
}
func NewAddressHandler(ms *mgo.Session) *AddressHandler {
return &AddressHandler{MS: ms.Clone()}
}
func (h *AddressHandler) Close() {
h.MS.Close()
}
// Add
type AddAddressInput struct {
Address *Address
}
type AddAddressOutput struct {
Error error
}
func (h *AddressHandler) AddAddress(in *AddAddressInput, out *AddAddressOutput) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("address")
out.Error = c.Insert(in.Address)
}
// Remove
type RemoveAddressInput struct {
AddressId string
}
type RemoveAddressOutput struct {
Error error
}
func (h *AddressHandler) RemoveAddress(in *RemoveAddressInput, out *RemoveAddressOutput) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("address")
out.Error = c.RemoveId(bson.ObjectIdHex(in.AddressId))
}
// Update
type UpdateAddressInput struct {
Address *Address
}
type UpdateAddressOutput struct {
Error error
}
func (h *AddressHandler) UpdateAddress(in *UpdateAddressInput, out *UpdateAddressOutput) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("address")
out.Error = c.UpdateId(in.Address.AccountId)
}
// GetAllByAccount
type GetAddressInput struct {
AccountId string
}
type GetAddressOutput struct {
Address []*Address
Error error
}
func (h *AddressHandler) GetAddress(in *GetAddressInput, out *GetAddressOutput) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("address")
out.Error = c.Find(bson.ObjectIdHex(in.AccountId)).All(&out.Address)
}
我想创建这个尚未模板代码的几乎副本。
"模板"代码:
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// --- Address
type %Model% struct {
Id bson.ObjectId `bson:"_id,omitempty"`
}
// --- %Model%Handler
type %Model%Handler struct {
MS *mgo.Session
}
func New%Model%Handler(ms *mgo.Session) *%Model%Handler {
return &%Model%Handler{MS: ms.Clone()}
}
func (h *%Model%Handler) Close() {
h.MS.Close()
}
// Add
type Add%Model%Input struct {
%Model% *%Model%
}
type Add%Model%Output struct {
Error error
}
func (h *%Model%Handler) Add%Model%(in *Add%Model%Input, out *Add%Model%Output) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("%Model%")
out.Error = c.Insert(in.%Model%)
}
// Remove %Model%
type Remove%Model%Input struct {
%Model%Id string
}
type Remove%Model%Output struct {
Error error
}
func (h *%Model%Handler) Remove%Model%(in *Remove%Model%Input, out *Remove%Model%Output) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("%Model%")
out.Error = c.RemoveId(bson.ObjectIdHex(in.%Model%Id))
}
// Update
type Update%Model%Input struct {
%Model% *%Model%
}
type Update%Model%Output struct {
Error error
}
func (h *%Model%Handler) Update%Model%(in *Update%Model%Input, out *Update%Model%Output) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("%Model%")
out.Error = c.UpdateId(in.%Model%.AccountId)
}
// GetAllByAccount
type Get%Model%Input struct {
AccountId string
}
type Get%Model%Output struct {
%Model% []*%Model%
Error error
}
func (h *%Model%Handler) Get%Model%(in *Get%Model%Input, out *Get%Model%Output) {
ms := h.MS.Copy()
defer ms.Close()
c := ms.DB("").C("%Model%")
out.Error = c.Find(bson.ObjectIdHex(in.AccountId)).All(&out.%Model%)
}
我需要添加或更改哪些内容,以便go generate
从此假设的模板输出。如您所见,Address
替换为%Model%
。
答案 0 :(得分:9)
我不是go generate的专家,但是AFAIK,调用go来执行可构建go文件中指定的命令,通常是为了生成新的东西。
为搜索特定指令的文件生成扫描://go:generate
,如果找到,它将执行后面的命令。
为了更好地理解正在发生的事情,让我们举一个简单的例子:模板go文件将有一个要替换的字符串。
让我们创建一个命令,将模板字符串NAME
替换为另一个字符串AkiRoss
:
#!/usr/bin/sh
sed "s/NAME/AkiRoss/g" $1 > $2
以下是go模板,请注意指令:
package main
import "fmt"
//go:generate ./repl.sh $GOFILE aki_$GOFILE
func main() {
fmt.Println("Hello,", NAME)
}
为方便起见,两个文件都在同一目录中,repl.sh是可执行的。如果我在目录中运行go generate
,则go工具会调用repl.sh templ.go aki_templ.go
,将$GOFILE
扩展为由generate处理的文件的名称。
这是我得到的:
package main
import "fmt"
//go:generate ./repl.sh $GOFILE aki_$GOFILE
func main() {
fmt.Println("Hello,", AkiRoss)
}
关于您的示例,您需要将//go:generate
指令放在某处。但是,该指令很可能包含在一个不同的文件中,而不是模板文件中,它调用替换脚本(类似于我制作的脚本)来生成构建所需的文件。
让我通过改变我的例子来解释这个:
#!/usr/bin/sh
sed "s/%NAME%/$3/g" $1 > $2
// This is a template for a go file
package main
import "fmt"
type %NAME% struct {
foo string
bar int
}
func (self *%NAME%) Perform() {
fmt.Println(self.foo, self.bar)
}
package main
import "fmt"
//go:generate ./repl.sh templ.txt foobar.go FooBar
func main() {
var fb = FooBar{"AkiRoss", -1}
fmt.Println("Running!")
fb.Perform()
}
运行go generate
将生成新文件
// This is a template for a go file
package main
import "fmt"
type FooBar struct {
foo string
bar int
}
func (self *FooBar) Perform() {
fmt.Println(self.foo, self.bar)
}
允许现在正确编译main:
$ go build
$ ./program
Running!
AkiRoss -1
我希望这澄清了。