嵌入式方法可以访问“父”字段吗?

时间:2013-11-23 21:12:55

标签: go

背景

我已经做了大量的规范阅读和代码测试,我认为答案是否定的,但我想确保我没有遗漏任何内容。

目标

基本上,我正在尝试为Go创建一个Active Record样式的ORM,因为我喜欢它的可读性以及它是如何从后端数据存储中抽象出来的。我宁愿通过在用户结构上嵌入常见的CRUD方法来编写user.Save()而不是data.Save(user)

示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    test := Foo{Bar: &Bar{}, Name: "name"}
    test.Test()
}

type Foo struct {
    *Bar
    Name string
}

func (s *Foo) Method() {
    fmt.Println("Foo.Method()")
}

type Bar struct {
}

func (s *Bar) Test() {
    t := reflect.TypeOf(s)
    v := reflect.ValueOf(s)
    fmt.Printf("model: %+v %+v %+v\n", s, t, v)
    fmt.Println(s.Name)
    s.Method()
}

http://play.golang.org/p/cWyqqVSKGH

问题

有没有办法让嵌入式方法可以访问顶级字段(不确定Go中的正确术语是什么)(例如:s.Names.Method()

感谢您将时间捐赠给新的Gopher。

2 个答案:

答案 0 :(得分:1)

Go不会对你所追求的内容提供任何支持:Test方法的接收者是Bar指针,并且无法判断它是否嵌入。

如果你真的想要走这条路线,一个选择是将interface{}成员添加到Bar,并要求将其设置为包含类型的类型。初始化此成员可能是创建该值的任何人的责任,或者可能需要调用者将值传递给某些ORM方法来设置它。这不是特别漂亮,但它可能是你能做的最好的。

有了这个,那么将API构建为db.Save(user)而不是user.Save()真的那么糟糕吗?前者提供了一种扩展到多个数据库的明显方式,而后者似乎更可能依赖于全局状态。

答案 1 :(得分:0)

(如果我理解你的问题,)不,嵌入不是继承。这听起来像你实际上是一个接口

type Saver interface {
    Save() error
}
然后有关各方可以实施。

您可以拥有一个公共结构base或任何实现常用方法的结构,然后每个更高级别的结构可以嵌入base以允许它们共享实现。