Mar*_*ace 156 oop constructor go
我有一个结构,我希望它用一些合理的默认值初始化.
通常,这里要做的是使用构造函数,但由于go不是传统意义上的OOP,因此它们不是真正的对象,也没有构造函数.
我注意到了init方法,但是在包级别.是否有类似的东西可以在结构级别使用?
如果不是在Go中这种类型的东西被接受的最佳实践是什么?
Den*_*ret 177
当零值不能产生合理的默认值时,或者某些参数对于struct初始化是必要的时,有一些构造函数的等价物.
假设你有这样的结构:
type Thing struct {
Name string
Num int
}
Run Code Online (Sandbox Code Playgroud)
那么,如果零值不合适,通常会构造一个带有NewThing
返回指针的函数的实例:
func NewThing(someParameter string) *Thing {
p := new(Thing)
p.Name = someParameter
p.Num = 33 // <- a very sensible default value
return p
}
Run Code Online (Sandbox Code Playgroud)
当你的结构很简单时,你可以使用这个压缩的结构:
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33}
}
Run Code Online (Sandbox Code Playgroud)
如果你不想返回指针,那么练习是调用函数makeThing
而不是NewThing
:
func makeThing(name string) Thing {
return Thing{name, 33}
}
Run Code Online (Sandbox Code Playgroud)
Vol*_*ker 123
实际上有两种被接受的最佳实践:
func New() YourTyp
或者如果在函数包中有多个这样的类型func NewYourType1() YourType1
,等等.记录你的类型的零值是否可用(在这种情况下,它必须由其中一个New...
函数设置.)对于"传统主义"oops:没有阅读文档的人将无法使用你的类型正确,即使他不能在未定义的状态下创建对象.)
zzz*_*zzz 35
Go有对象.对象可以有构造函数(尽管不是自动构造函数).最后,Go是一种OOP语言(数据类型附带了方法,但无可否认,OOP的定义是无穷无尽的.)
尽管如此,公认的最佳实践是为您的类型编写零个或多个构造函数.
由于@dystroy在我完成这个答案之前发布了他的答案,让我只添加他的示例构造函数的替代版本,我可能会将其编写为:
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33} // <- 33: a very sensible default value
}
Run Code Online (Sandbox Code Playgroud)
我想向您展示此版本的原因是,通常可以使用"内联"文字而不是"构造函数"调用.
a := NewThing("foo")
b := &Thing{"foo", 33}
Run Code Online (Sandbox Code Playgroud)
现在*a == *b
.
Seb*_*tos 10
Go中没有默认构造函数,但您可以为任何类型声明方法.您可以习惯于声明一个名为"Init"的方法.不确定这是否与最佳实践有关,但它有助于保持名称简短而不会失去清晰度.
package main
import "fmt"
type Thing struct {
Name string
Num int
}
func (t *Thing) Init(name string, num int) {
t.Name = name
t.Num = num
}
func main() {
t := new(Thing)
t.Init("Hello", 5)
fmt.Printf("%s: %d\n", t.Name, t.Num)
}
Run Code Online (Sandbox Code Playgroud)
结果是:
Hello: 5
Run Code Online (Sandbox Code Playgroud)
Liu*_*hyn 10
在 Go 中,可以使用返回指向已修改结构的指针的函数来实现构造函数。
type Colors struct {
R byte
G byte
B byte
}
// Constructor
func NewColors (r, g, b byte) *Colors {
return &Color{R:r, G:g, B:b}
}
Run Code Online (Sandbox Code Playgroud)
为了弱依赖和更好的抽象,构造函数不返回指向结构的指针,而是返回该结构实现的接口。
type Painter interface {
paintMethod1() byte
paintMethod2(byte) byte
}
type Colors struct {
R byte
G byte
B byte
}
// Constructor return intreface
func NewColors(r, g, b byte) Painter {
return &Color{R: r, G: g, B: b}
}
func (c *Colors) paintMethod1() byte {
return c.R
}
func (c *Colors) paintMethod2(b byte) byte {
return c.B = b
}
Run Code Online (Sandbox Code Playgroud)
我喜欢这篇博客文章中的解释:
New函数是Go约定,用于创建创建供应用程序开发人员使用的核心类型或其他类型的包的约定。查看如何在log.go,bufio.go和cypto.go中定义和实现New:
// New creates a new Logger. The out variable sets the
// destination to which log data will be written.
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) * Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
Run Code Online (Sandbox Code Playgroud)
// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) * Reader {
return NewReaderSize(rd, defaultBufSize)
}
Run Code Online (Sandbox Code Playgroud)
// New returns a new hash.Hash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
panic("crypto: requested hash function is unavailable")
}
Run Code Online (Sandbox Code Playgroud)
由于每个程序包都充当命名空间,因此每个程序包都可以具有自己的New版本。在bufio.go中可以创建多种类型,因此没有独立的New函数。在这里,您会发现类似NewReader和NewWriter的功能。
另一种方式是;
package person
type Person struct {
Name string
Old int
}
func New(name string, old int) *Person {
// set only specific field value with field key
return &Person{
Name: name,
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想强制使用工厂函数,请使用小写的第一个字符来命名您的结构(您的类)。那么,就不可能直接实例化结构体,需要工厂方法。
这种基于第一个字符小写/大写的可见性也适用于结构字段和函数/方法。如果您不想允许外部访问,请使用小写。
归档时间: |
|
查看次数: |
82714 次 |
最近记录: |