Golang 嵌入式结构体类型

Posted

技术标签:

【中文标题】Golang 嵌入式结构体类型【英文标题】:Golang embedded struct type 【发布时间】:2017-12-24 16:03:13 【问题描述】:

我有这些类型:

type Value interface

type NamedValue struct 
    Name  string
    Value Value


type ErrorValue struct 
    NamedValue
    Error error

我可以使用v := NamedValueName: "fine", Value: 33,但我不能使用e := ErrorValueName: "alpha", Value: 123, Error: err

好像嵌入语法没问题,但是用起来不行?

【问题讨论】:

【参考方案1】:

嵌入式类型是(未命名的)字段,由非限定类型名称引用。

Spec: Struct types:

使用类型声明但没有显式字段名称的字段是匿名字段,也称为嵌入字段或结构中类型的嵌入。必须将嵌入类型指定为类型名称T 或指向非接口类型名称*T 的指针,而T 本身可能不是指针类型。 不合格的类型名作为字段名。

那就试试吧:

e := ErrorValueNamedValue: NamedValueName: "fine", Value: 33, Error: err

如果您在复合文字中省略字段名称也可以:

e := ErrorValueNamedValue"fine", 33, err

尝试Go Playground 上的示例。

【讨论】:

在使用嵌入类型的结构中命名字段时是否有最佳实践? @SeanPianka 你是什么意思?命名字段和嵌入存在争议:嵌入字段是匿名字段。 省略字段名称确实如前所述,但是如果您的结构有很多字段,那么不幸的是,您还需要传递它们。例如对于具有四个属性的结构,如果您的嵌入式结构是第一个字段之一,那么您需要像 ErrorValuenil, NamedValue"fine", 33, nil, nil 一样对其进行初始化,这看起来不像传递嵌入式结构的非限定类型名称那么干净。提到的第一种方法要好一些,但我不禁觉得它有点不必要的复杂和笨拙(至少与 Python 之类的语言相比)【参考方案2】:

对于深度嵌套的结构,接受的答案的语法有点冗长。比如这个:

package main

import (
    "fmt"
)

type Alternative struct 
    Question
    AlternativeName string


type Question struct 
    Questionnaire
    QuestionName  string


type Questionnaire struct 
    QuestionnaireName string


func main() 
    a := Alternative
        Question: Question
            Questionnaire: Questionnaire
                QuestionnaireName: "q",
            ,
        ,
    
    fmt.Printf("%v", a)

(Go playground)

可以这样改写:

a := Alternative
a.QuestionnaireName = "q"

【讨论】:

【参考方案3】:

除了icza的精彩回答。

你可以这样做:

v := NamedValueName: "fine", Value: 33
e := ErrorValueNamedValue:v, Error: err

它工作得很好。查看示例Here

【讨论】:

以上是关于Golang 嵌入式结构体类型的主要内容,如果未能解决你的问题,请参考以下文章

golang 结构体嵌入和匿名成员

golang中级进阶(二):结构体

golang结构体组合与“多态” 2021-08-06

Golang basic_leaming结构体

Golang basic_leaming结构体

Golang复制结构体