给定Go中的以下软件包,是否可以防止Barwith 的直接初始化而 Bar{..}不会Bar从软件包中暴露出来?
包bar:
package bar
import ()
type Bar struct {
A string
B string
}
func NewBar(baz string) Bar{
return Bar{A:baz, B:baz+baz}
}
Run Code Online (Sandbox Code Playgroud)
包main:
package main
import (
"fmt"
"./bar"
)
func main() {
x := bar.NewBar("sad") //all bars should be created with this
y := bar.Bar{A: "fadss"} //and this should be disallowed
bzzBar(x)
bzzBar(y)
}
func bzzBar(bzz bar.Bar) { //but I can't do 'Bar -> bar' because I want to use the type
fmt.Println(bzz)
}
Run Code Online (Sandbox Code Playgroud)
我的直觉说这无法完成,所以这也是一个有效的答案。
没有办法阻止Bar{}或Bar{A: "foo"}。
要以您想要的方式控制结构,您可以返回一个接口而不是导出结构本身。
给出的例子:
package bar
type Bar interface{
A() string
B() string
// if you need setters
SetA(string)
SetB(string)
}
type bar struct {
a string
b string
}
func (b *bar) A() string { return b.a }
func (b *bar) B() string { return b.b }
func (b *bar) SetA(val string) { b.a = val }
func (b *bar) SetB(val string) { b.b = val }
func NewBar(baz string) Bar {
return &bar{a:baz, b:baz+baz}
}
Run Code Online (Sandbox Code Playgroud)
Go标准库中使用的习惯用法是:
package bar
package bar
import (
"fmt"
)
type Bar struct {
a string
b string
}
func New(baz string) *Bar {
return &Bar{a: baz, b: baz + baz}
}
func (b *Bar) BzzBar() {
fmt.Println(*b)
}
Run Code Online (Sandbox Code Playgroud)
package main
package main
import (
"bar"
)
func main() {
x := bar.New("sad") //all bars should be created with this
x.BzzBar()
// error: unknown bar.Bar field 'A' in struct literal
// y := bar.Bar{A: "fadss"} //and this should be disallowed
}
Run Code Online (Sandbox Code Playgroud)
输出:
{sad sadsad}
Run Code Online (Sandbox Code Playgroud)
附录:
当通过声明或调用 make 或 new 分配内存来存储值并且未提供显式初始化时,将为内存提供默认初始化。此类值的每个元素都设置为其类型的零值:对于布尔值为 false,对于整数为 0,对于浮点数为 0.0,对于字符串为 "",对于指针、函数、接口、切片、通道和映射为 nil。此初始化是递归完成的,因此,例如,如果未指定值,则结构数组的每个元素都将其字段归零。
Go 标准库中使用的另一个习惯用法是使零值有意义。例如,如果new尚未显式初始化,它将具有零默认值false。
type Bar struct {
new bool
a string
b string
}
Run Code Online (Sandbox Code Playgroud)
例如,
package bar
import (
"fmt"
)
type Bar struct {
new bool
a string
b string
}
func New(baz string) *Bar {
return &Bar{new: true, a: baz, b: baz + baz}
}
func (b *Bar) notnew() {
if b == nil || !b.new {
panic("bar.Bar not bar.New")
}
}
func (b *Bar) Bzz() {
b.notnew()
fmt.Println(*b)
}
Run Code Online (Sandbox Code Playgroud)
。
package main
import (
"bar"
)
func main() {
x := bar.New("sad") //all bars should be created with this
x.Bzz()
// error: unknown bar.Bar field 'A' in struct literal
// y := bar.Bar{A: "fadss"} //and this should be disallowed
// var b bar.Bar
// panic: bar.Bar not bar.New
// b.Bzz()
// var b = bar.Bar{}
// panic: bar.Bar not bar.New
// b.Bzz()
// var bp *bar.Bar
// panic: bar.Bar not bar.New
// bp.Bzz()
// var bp = new(bar.Bar)
// panic: bar.Bar not bar.New
// bp.Bzz()
}
Run Code Online (Sandbox Code Playgroud)
输出:
{true sad sadsad}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
577 次 |
| 最近记录: |