duanmei2459 2014-10-20 09:10
浏览 12
已采纳

前往:禁止直接进行结构初始化

Given the following packages in Go, is it possible to prevent the direct initialization of Bar with Bar{..} without de-exposing Bar from the package?

package bar:

package bar

import ()

type Bar struct {
    A string
    B string
}

func NewBar(baz string) Bar{
    return Bar{A:baz, B:baz+baz}
}

package 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)
}

My gut feeling says this can't be done, so that is also a valid answer.

  • 写回答

4条回答 默认 最新

  • dousi3362 2014-10-20 13:45
    关注

    The idiom used in the Go standard library is:

    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)
    }
    

    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
    }
    

    Output:

    {sad sadsad}
    

    ADDENDUM:

    The Go Programming Language Specification

    The zero value

    When memory is allocated to store a value, either through a declaration or a call of make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of such a value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.

    Another idiom used in the Go standard library is to make zero values meaningful. For example, if new has not been explicitly initialized it will have the zero value default of false.

    type Bar struct {
        new bool
        a   string
        b   string
    }
    

    For example,

    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)
    }
    

    .

    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()
    }
    

    Output:

    {true sad sadsad}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog