go - 使用嵌入式别名在不同包中的结构上定义方法是否有效?

标签 go methods package

除非我的测试是错误的,否则所有其他选项,包括使用普通函数,比使用嵌入式别名在不同包中定义方法所花的时间大约长 35%。我可能做错了什么,我很想知道它是什么。有关完整的详细信息,请参阅 this repository .

[编辑] 感谢您的评论/建议。以下仅显示与比较“方法”和“方法”相关的代码。前者使用模型包中定义的典型方法以及结构。 “meth”选项使用在 datactrl 包中定义的嵌入式别名来定义方法。第一个代码示例包括结构定义和测试中使用的结构的导出默认实例。

来自包模型,文件models.go

type CmntData struct {
    ID          int
    Slug        string
    Title       string
    PageID      int
    Text        string
    DateCreated time.Time
    CreatedBy   int
}

var DefaultCD = CmntData{ID: 100, Title: "Demo Comment",
Text: "This is a test comment", PageID: 1000, CreatedBy: 4242}


// Local methods called by the "method" test

func (cd *CmntData) NewComment(ncd CmntData) *CmntData {

    ncd.DateCreated = time.Now()

    return &ncd
}

func (cd *CmntData) DefaultComment(cnt int) *CmntData {

    dcd := DefaultCD
    dcd.Slug = "demo-comment-" + strconv.Itoa(cnt + 1)

    return cd.NewComment(dcd)
}

来自包 datactrl,文件 comments.go

// Types and method definitions used to add methods to models.CmntData

type roCmntData struct {
    ModelCD models.CmntData
}

type roCD struct{}

// roComment allows us to effectively add methods to models.CmntData.
// Data and "local" methods defined for models.CmntData are accessible.
type roComment struct {
    *roCmntData  // Provides access to models.CmntData
    *roCD        // Required to make the magic happen
}

// Other packages must use Rcd to access methods added to models.CmntData
var Rcd = roComment {
    roCmntData: &roCmntData{},
    roCD: &roCD{},
}

// Remote methods called by the "meth" test

func (cd *roComment) NewComment(ncd models.CmntData) *models.CmntData {

    cd.roCmntData.ModelCD = ncd
    cd.ModelCD.DateCreated = time.Now()

    return &cd.ModelCD
}

func (cd *roComment) DefaultComment(cnt int) *models.CmntData {

    dcd := models.DefaultCD
    dcd.Slug = "demo-comment-" + strconv.Itoa(cnt + 1)

    return cd.NewComment(dcd)
}

来自包 main,文件 main.go

if cmd == "method" {
    tstart := time.Now()
    dcd := models.CmntData{}
    for i := 0; i < limit; i++ {
        defCD = dcd.DefaultComment(i)
    }
    tfinish := time.Now()
    elapsed = tfinish.Sub(tstart)
}

if cmd == "meth" {
    tstart := time.Now()

    // datactrl.Rcd provides access to remote models.CmntData methods
    dcd := &datactrl.Rcd 
    for i := 0; i < limit; i++ {
        defCD = dcd.DefaultComment(i)
    }
    tfinish := time.Now()
    elapsed = tfinish.Sub(tstart)
}

Screen shot of results取 40 次循环的平均值,其中每个循环返回一百万次测试运行的平均值。作为记录,“func”和“function”测试都在“method”发布结果的 2ms 内完成。

最佳答案

实际上@JimB 回答了我的问题,但它在关于该问题的评论中。

答案似乎是典型的方法,在与它们成为其一部分的结构相同的包中定义,需要额外的内存分配。结果,我称为远程 方法定义的东西获得了微小的优势。

请记住,边缘可能不值得做一些需要大量评论才能弄清楚发生了什么的事情。另一方面,如果您需要/想要将数据操作与数据定义分开,远程 方法将允许您这样做,并且您可以在每次调用中节省几微秒的时间作为额外的好处. :)

他建议使用内置测试的 Go 基准工具,听起来不错。我会亲自调查。

关于go - 使用嵌入式别名在不同包中的结构上定义方法是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45666430/

相关文章:

Java - 我是否必须在包包含的所有类中注释包?

go - "glide get"和"go get"安装不同的版本

go - 不同的结构重用相同的方法

java - id存储在map中的线程的run方法

javascript - JS 中 .push 处的代码损坏。

php - PEAR 包安装失败

govendor 不导入较新的版本

json - 限制 Json 模式中的返回字段

javascript - 在 'this' 和对象的原型(prototype)方法中使用 'constructor' 时如何正确返回值?

service - 如何获取 Linux 上的基本包安装位置?