dounei5721 2016-05-21 11:01
浏览 29
已采纳

在这个例子中解释去生成

I'm having difficulties understanding go generate. I also find barely any posts dealing with go generate.

please explain go generate in this following example:

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)
}

I would like to create almost carbon copies of this not yet template code.

the "template" code:

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%)
}

What do I need to add or change so I can go generate output from this supposed template. As you can see everything Address is replaced with %Model%.

  • 写回答

1条回答 默认 最新

  • douyanxing6054 2016-05-22 04:03
    关注

    I am not expert with go generate, but AFAIK, go generate is called to perform commands specified in buildable go files, normally with the intent to produce something new.

    Generate scans for files searching for a specific directive: //go:generate and, if found, it will execute the command following it.

    To understand better what's happening, let's make a simple example: a template go file will have a string to be replaced.

    Example 1

    Let's make a command that replace the template string, NAME, with another string, AkiRoss:

    repl.sh

    #!/usr/bin/sh
    sed "s/NAME/AkiRoss/g" $1 > $2
    

    Here follows the go template, note the directive:

    templ.go

    package main
    
    import "fmt"
    
    //go:generate ./repl.sh $GOFILE aki_$GOFILE
    
    func main() {
        fmt.Println("Hello,", NAME)
    }
    

    Both files are in the same directory, for convenience, and repl.sh is executable. If I run go generate in the directory, the go tool will call repl.sh templ.go aki_templ.go, being $GOFILE expanded to be the name of the file processed by generate.

    Here's what I get:

    aki_templ.go

    package main
    
    import "fmt"
    
    //go:generate ./repl.sh $GOFILE aki_$GOFILE
    
    func main() {
            fmt.Println("Hello,", AkiRoss)
    }
    

    Example 2

    Regarding your example, you will need to place the //go:generate directive somewhere. It is likely, however, that the directive will be included in a different file, not the template file, that calls a replacement script, similar to the one I made, to produce a file which is needed for building.

    Let me explain this better by changing my example:

    repl.sh

    #!/usr/bin/sh
    sed "s/%NAME%/$3/g" $1 > $2
    

    templ.txt

    // 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)
    }
    

    main.go

    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()
    }
    

    Running go generate will produce a new file

    foobar.go

    // 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)
    }
    

    which allows now to compile correctly the main:

    $ go build
    $ ./program
    Running!
    AkiRoss -1
    

    I hope this clarified.

    References

    More details here, and a better example is here.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化