Golang struct uses factory method to create structure instance

Structure Factory

The Go language does not support constructor methods like object-oriented programming languages, but it is easy to implement "constructor factory" methods in Go. For convenience, a factory is usually defined for a type, and by convention, the name of the factory starts with new or New . Suppose the following File structure type is defined:

type File struct {
    fd      int     // 文件描述符
    name    string  // 文件名
}

Here is the factory method for this struct type, which returns a pointer to a struct instance:

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }

    return &File{fd, name}
}

and call it like this:

f := NewFile(10, "./test.txt")

In the Go language, initialization is often used in the factory method as above to simply implement the constructor.

If File is a structure type, then the expressions new(File) and &File{} are equivalent .

This can be compared to the clumsy initialization in most object-oriented programming languages: File f = new File(...) .

We can say that a factory instantiates an object of a type , as in class-based OOP languages.

If you want to know how much memory an instance of a structure type T takes up, you can use: size := unsafe.Sizeof(T{}).

How to force the use of factory methods

By applying the visibility rules see  Section 4.2.1 , Section 9.5 it is possible to prohibit the use of new functions, force users to use factory methods, and thus make types private, as in object-oriented languages.

type matrix struct {
    ...
}

func NewMatrix(params) *matrix {
    m := new(matrix) // 初始化 m
    return m
}

Using factory methods in other packages:

package main
import "matrix"
...
wrong := new(matrix.matrix)     // 编译失败(matrix 是私有的)
right := matrix.NewMatrix(...)  // 实例化 matrix 的唯一方式

 

map and struct vs new() and make() 

The two built-in functions new and make have already been explained once in  Section 7.2.4  with the example of slices.

So far we've seen  make() two of the three types that can be used:

slices  /  maps / channels(见第 14 章)

The following example illustrates the difference between using new and make on a map, and possible errors:

Example 10.4 new_make.go (does not compile)

type Foo map[string]string

type Bar struct {
    thingOne string
    thingTwo int
}

func main() {

    // OK
    y := new(Bar)
    (*y).thingOne = "hello"
    (*y).thingTwo = 1

    // NOT OK
    z := make(Bar) // 编译错误:cannot make type Bar
    (*z).thingOne = "hello"
    (*z).thingTwo = 1

    // OK
    x := make(Foo)
    x["x"] = "goodbye"
    x["y"] = "world"

    // NOT OK
    u := new(Foo)
    (*u)["x"] = "goodbye" // 运行时错误!! panic: assignment to entry in nil map
    (*u)["y"] = "world"
}

Trying to make() a struct variable will throw a compile error, which isn't too bad, but new()ing a map and trying to fill it with data will throw a runtime error! Because new(Foo) returns a pointer to nil, it has not yet been allocated memory. So be careful when using map.

Guess you like

Origin blog.csdn.net/qq_34556414/article/details/130111320