Golang的结构体字面量语法与未导出字段

huangapple go评论95阅读模式
英文:

Golang struct literal syntax with unexported fields

问题

我有一个相当大的结构体,直到刚才我都是使用结构体字面值语法进行实例化的,例如:

Thing{
  "the name",
  ...
}

我刚刚在Thing结构体中添加了一个未导出的字段,现在Go报错了:在Thing字面值中隐式赋值了未导出的字段'config'

即使在结构体上现在有一个未导出的字段,我是否有办法继续使用字面值语法?

英文:

I've got a largish struct which until just now I was instantiating with the struct literal syntax, e.g.:

Thing{
  "the name",
  ...
}

I've just added an unexported field the Thing struct and now Go is complaining: implicit assignment of unexported field 'config' in Thing literal.

Is there any way I can continue using the literal syntax even though there's now an unexported field on the struct?

答案1

得分: 18

你只能使用复合字面量来创建另一个包中定义的结构类型的值,如果在字面量中使用了_keyed values_,因为这样你就不需要为所有字段提供初始值,所以可以省略未导出的字段(只有声明包才能设置/更改)。

如果类型在同一个包中声明,你也可以设置未导出的字段:

t := Thing{
    Name:           "the name",
    someUnexported: 23,
}

但是,如果类型在另一个包中声明,你只能为导出的字段提供初始值,这应该不足为奇:

t := otherpackage.Thing{
    Name: "the name",
    // someUnexported 将隐式地成为其类型的零值
}

如果你需要具有与其类型的零值不同的值的结构的值,那么包本身必须导出某种构造函数或初始化程序(或设置方法),因为在包的外部,你无法更改/设置未导出的字段。

参考相关问题:https://stackoverflow.com/questions/38369350/how-to-clone-a-structure-with-unexported-field/38370382#38370382

英文:

You can only use composite literals to create values of struct types defined in another package if you use keyed values in the literal, because then you are not required to provide initial values for all fields, and so you can leave out unexported fields (which only the declaring package can set / change).

If the type is declared in the same package, you can set unexported fields too:

t := Thing{
    Name:           "the name",
    someUnexported: 23,
}

But you can only provide initial values for exported fields if the type is declared in another package, which is not a surprise I guess:

t := otherpackage.Thing{
    Name: "the name",
    // someUnexported will implicitly be its zero value
}

If you need values of the struct where the unexported fields have values other than the zero value of their types, the package itself must export some kind of constructor or initializer (or setter method), because from the outside (of the package), you can't change / set unexported fields.

See related question: https://stackoverflow.com/questions/38369350/how-to-clone-a-structure-with-unexported-field/38370382#38370382

答案2

得分: 11

还有一个要补充的点。如果一个结构体的所有属性都希望在包外可见,它们应该以大写字母开头。例如:

t := Thing
{

    Name: "the name", // <-- 这样是可以的,因为Name以大写字母开头

    someUnexported: 23, // <-- 这样是不行的,因为someUnexported以小写字母开头
}
英文:

One more point to add. All properties of a structure should start with capital letter if they are supposed to be visible outside the package. For example:

t := Thing
{

    Name: &quot;the name&quot;, // &lt;-- This will work because Name start with capital letter 

    someUnexported: 23, // &lt;-- this wont work because someUnexported starts with small letter
}

huangapple
  • 本文由 发表于 2017年7月20日 19:26:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/45213365.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定