我在理解 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)
}
我想创建这个尚未模板代码的几乎副本。
"template"代码:
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%)
}
我需要添加或更改什么才能从这个假设的模板生成输出。如您所见,Address 全部替换为 %Model%。
最佳答案
我不是 go generate 的专家,但据我所知,调用 go generate 来执行可构建的 go 文件中指定的命令,通常是为了产生新的东西。
为搜索特定指令的文件生成扫描://go:generate,如果找到,它将执行后面的命令。
为了更好地理解发生了什么,让我们举一个简单的例子:模板 go 文件将有一个字符串被替换。
让我们创建一个命令,用另一个字符串 AkiRoss 替换模板字符串 NAME:
#!/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)
}
现在可以正确编译主要内容:
$ go build
$ ./program
Running!
AkiRoss -1
我希望这能得到澄清。
关于go - 在这个例子中解释go generate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37362054/
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
我今天看到了一个ruby代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem
如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
我真的只是不确定这意味着什么或我应该做什么才能让网页在我的本地主机上运行。现在它只是显示一个错误,上面写着“我们很抱歉,但出了点问题。”当我运行railsserver并在chrome中打开localhost:3000时。这是控制台输出:StartedGET"/users/sign_in"for127.0.0.1at2013-07-0512:07:07-0400ProcessingbyDevise::SessionsController#newasHTMLCompleted500InternalServerErrorin55msNoMethodError(undefinedmethod`
好的,所以我有了我正在使用的应用程序的这种方法,它可以在生产中使用。我的问题为什么这行得通?这是新的Ruby语法吗?defeditload_elements(current_user)unlesscurrent_user.role?(:admin)respond_todo|format|format.json{render:json=>@user}format.xml{render:xml=>@user}format.htmlendrescueActiveRecord::RecordNotFoundrespond_to_not_found(:json,:xml,:html)end
你能解释一下吗?我想评估来自两个不同来源的值和计算。一个消息来源为我提供了以下信息(以编程方式):'a=2'第二个来源给了我这个表达式来评估:'a+3'这个有效:a=2eval'a+3'这也有效:eval'a=2;a+3'但我真正需要的是这个,但它不起作用:eval'a=2'eval'a+3'我想了解其中的区别,以及如何使最后一个选项起作用。感谢您的帮助。 最佳答案 您可以创建一个Binding,并将相同的绑定(bind)与每个eval相关联调用:1.9.3p194:008>b=binding=>#1.9.3p194:009>eva
我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有
我使用Ruby编程已经有一段时间了,现在只使用Ruby的标准MRI实现,但我一直对我经常听到的其他实现感到好奇。前几天我在读有关Rubinius的文章,这是一个用Ruby编写的Ruby解释器。我试着在不同的地方查找它,但我很难弄清楚这样的东西到底是如何工作的。我在编译器或语言编写方面从来没有太多经验,但我真的很想弄明白。一门语言究竟如何才能被自己解释?编译中是否有一个我不明白这有意义的基本步骤?有人可以像我是个白痴一样向我解释这个吗(因为无论如何这都不会太离谱) 最佳答案 它比你想象的要简单。Rubinius并非100%用Ruby编
(跟进我之前的问题,Ruby:howcanIcopyavariablewithoutpointingtothesameobject?)我正在编写一个简单的Ruby程序来在.svg文件中进行一些替换。第一步是从文件中提取信息并将其放入数组中。为了避免每次调用此函数时都从磁盘读取文件,我尝试使用memoize设计模式-在第一次调用后的每次调用中都使用缓存结果。为此,我使用了一个在函数之前定义的全局变量。但是,即使我在返回局部变量之前将该变量.dup为局部变量,调用该变量的函数仍在修改全局变量。这是我的实际代码:#memoizetokeepfromhavingtoreadoriginalfi