说明:
Golang 的结构体没有构造函数,通常可以使用工厂模式来解决这个问题。
有一个这样的需求:
一个结构体的声明是这样的:
package model
type Student struct { Name string...
}
因为这里的Student 的首字母S 是大写的,如果我们想在其它包创建 Student 的实例(比如main 包), 引入 model 包后,就可以直接创建 Student 结构体的变量(实例)。但是问题来了,如果首字母是小写的, 比如 是 type student struct {....} 就不不行了,怎么办---> 工厂模式来解决.
使用工厂模式来解决问题
- 使用工厂模式实现跨包创建结构体实例(变量)的案例:
如果 model 包的 结构体变量首字母大写,引入后,直接使用, 没有问题
student.go
package model
//定义结构体
//当结构体名称的为首字母大写时,可以被外部的包调用
type Student struct {
Name string
Score float64
}
main.go
package main
import (
"fmt"
"go_code/factory/model"
)
func main() {
//创建Student实例
var stu = model.Student{
Name: "tom",
Score: 89.7,
}
fmt.Println(stu)
}
如果 model 包的 结构体变量首字母小写,引入后,不能直接使用, 可以工厂模式解决
student.go
package model
//定义结构体
type student struct {
Name string
Score float64
}
//因为student结构体首字母小写,因此只能够在当前包model中使用
//这时我们可以通过工厂模式来解决
//写一个工厂模式的函数,相当于构造函数
func NewStudent(name string, score float64) *student {
return &student{
Name: name,
Score: score,
}
}
main.go
package main
import (
"fmt"
"go_code/factory/model"
)
func main() {
//创建Student实例
// var stu = model.Student{
// Name: "tom",
// Score: 89.7,
// }
//当student结构体为首字母小写时,我们可以通过工厂模式来解决
var stu = model.NewStudent("tom", 86.7)
fmt.Println(*stu)
fmt.Println("name=", stu.Name, " score=", stu.Score)
//fmt.Println("name=", (*stu).Name, " score=", (*stu).Score)
}
思考题:
如果 model 包的 student 的结构体的字段 Score 改成 score,我们还能正常访问吗?又应该如何解决这个问题呢?
student.go
package model
//定义结构体
type student struct {
Name string
score float64
}
//因为student结构体首字母小写,因此只能够在当前包model中使用
//这时我们可以通过工厂模式来解决
//写一个工厂模式的函数,相当于构造函数
func NewStudent(name string, score float64) *student {
return &student{
Name: name,
score: score, //其他包不能直接访问
}
}
//如果score字段首字母小写,则,在其他包中不可以直接访问,我们可以提供一个方法
func (s *student) GetScore() float64 {
return s.score
}
main.go
package main
import (
"fmt"
"go_code/factory/model"
)
func main() {
//创建Student实例
// var stu = model.Student{
// Name: "tom",
// Score: 89.7,
// }
//当student结构体为首字母小写时,我们可以通过工厂模式来解决
var stu = model.NewStudent("tom", 86.7)
fmt.Println(*stu)
fmt.Println("name=", stu.Name, " score=", stu.GetScore())
//fmt.Println("name=", (*stu).Name, " score=", (*stu).Score)
}
关于这个代码的注意事项:
-
关于大小写
-
)小写字母开头的函数只在本包内可见,大写字母开头的函数才能被其他包使用。这个规则也适用于类型和变量的可见性。
-
)大小写影响了可见性,大写字母开头等同于public,小写字母开头等同于private,这种做法不仅免除了public、private关键字,更重要的是统一了命名风格。
-
-
结构体方法参数
-
)如果要求对象必须以指针传递,这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。
-
)只有在你需要修改对象的时候,才必须用指针。
-
更多资料参考: Go设计模式(1)