组成和嵌入

组合提供了继承的替代方法。结构可以在其声明中按名称包含另一种类型:

type Request struct {
    Resource string
}

type AuthenticatedRequest struct {
    Request
    Username, Password string
}

在上面的例子中,AuthenticatedRequest 将包含四个公共成员:ResourceRequestUsernamePassword

可以实例化复合结构,并使用与普通结构相同的方式:

func main() {
    ar := new(AuthenticatedRequest)
    ar.Resource = "example.com/request"
    ar.Username = "bob"
    ar.Password = "P@ssw0rd"
    fmt.Printf("%#v", ar)
}

在操场上玩

嵌入

在前面的示例中,Request 是嵌入字段。也可以通过嵌入不同类型来实现组合。例如,这可用于装饰具有更多功能的 Struct。例如,继续使用 Resource 示例,我们需要一个格式化 Resource 字段内容的函数,用 http://https://作为前缀。我们有两个选择:在 AuthenticatedRequest 上创建新方法或从不同的结构中嵌入它:

type ResourceFormatter struct {}

func(r *ResourceFormatter) FormatHTTP(resource string) string {
    return fmt.Sprintf("http://%s", resource)
}
func(r *ResourceFormatter) FormatHTTPS(resource string) string {
    return fmt.Sprintf("https://%s", resource)
}

type AuthenticatedRequest struct {
    Request
    Username, Password string
    ResourceFormatter
}

现在主要功能可以执行以下操作:

func main() {
    ar := new(AuthenticatedRequest)
    ar.Resource = "www.example.com/request"
    ar.Username = "bob"
    ar.Password = "P@ssw0rd"

    println(ar.FormatHTTP(ar.Resource))
    println(ar.FormatHTTPS(ar.Resource))

    fmt.Printf("%#v", ar)
}

看看 AuthenticatedRequest 有一个 ResourceFormatter 嵌入式结构。

它的缺点是你不能访问你作文之外的对象。所以 ResourceFormatter 无法访问 AuthenticatedRequest 的成员。

在操场上玩