Go中无需New关键字初始化含未导出字段结构体的问题
解决Go中跨包初始化未导出字段结构体的问题(不用New关键字)
首先得搞清楚你报错的根源:Go的包可见性规则是小写开头的字段属于未导出字段,只能在定义它的包内部直接赋值。你在其他包用&run.MyRunner{"a/b/c/"}初始化时,本质是在给run包内的未导出字段path赋值,这直接违反了规则,所以编译器才会报错。
不用New关键字当然能解决,给你几个实用方案:
方案1:直接导出字段(最简单)
如果你不介意把path字段暴露给外部包,直接把它改成大写开头的导出字段:
// 在run包内 type MyRunner struct { Path string }
之后跨包就能直接用结构体字面量初始化了:
runner := &run.MyRunner{Path: "a/b/c/"}
这个方案最省事,但如果你的业务逻辑需要隐藏path的内部实现,就跳过这个方案。
方案2:用非New开头的构造函数
在run包内写一个自定义的构造函数,不用New开头就行,比如叫MyRunnerWithPath:
// 在run包内 func MyRunnerWithPath(path string) *MyRunner { return &MyRunner{path: path} }
然后跨包调用这个函数来初始化对象:
runner := run.MyRunnerWithPath("a/b/c/")
既绕开了New关键字,又能安全地给未导出字段赋值,完美符合你的需求。
方案3:零值初始化后用方法设置字段
如果希望先创建一个空对象再配置参数,可以在run包给MyRunner加一个导出的Set方法:
// 在run包内 func (r *MyRunner) SetPath(newPath string) { r.path = newPath }
之后跨包可以这么用:
runner := &run.MyRunner{} // 先创建零值对象 runner.SetPath("a/b/c/") // 通过导出方法设置内部字段
这种方式也完全不用New关键字,还能保留字段的未导出特性。
另外补充一句:如果是在run包内部使用MyRunner,直接用&MyRunner{"a/b/c/"}是完全没问题的,报错只发生在跨包访问未导出字段的场景哦。
内容的提问来源于stack exchange,提问作者tj holwik
相关产品推荐
相关产品推荐

