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.

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

报告相同问题?

悬赏问题

  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗