本文总结了结构体的工厂模式、tag的使用、匿名字段和方法
目录
struct的工厂模式
Go中的struct无构造函数,我们可通过工厂模式初始化
package main
import "fmt"
//工厂模式,Go中无构造函数,我们用工厂模式代替
type student struct {
Name string
Age int
}
func NewStudent(name string, age int) *student {
return &student{
Name: name,
Age: age,
}
}
func main() {
S := new(student)
S = NewStudent("tony", 20)
fmt.Println(S)
}
struct中tag的使用
我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获得,最常用的场景就是json序列化和反序列化。如下面代码所示,因为结构体中均为小写开头,json序列化后输出的结果为空,用大写则正常。那么我们要用小写怎么办呢?此时tag可发挥作用了
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
name string
age int
score int
}
func main() {
var stu Student = Student{
name: "stu01",
age: 18,
score: 80,
}
data, err := json.Marshal(stu)
if err != nil {
fmt.Printf("json encode stu faild,error")
return
}
fmt.Println(string(data))
}
我们加入tag后,虽然结构体中为大写,但如下输出结果图所示,用tag后json打包的均为小写
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Score int `json:"score"`
}
匿名字段
结构体中字段可以没有名字,即匿名字段。匿名字段的访问如下代码所示:
注:匿名字段里实现了继承
package main
import (
"fmt"
"time"
)
type Cart struct {
name string
age int
}
type Train struct {
Cart
int
start time.Time
}
func main() {
var t Train //匿名字段的访问
t.Cart.name = "train" //可直接访问Cart结构体中的name和age
t.Cart.age = 100
t.int = 200
fmt.Println(t)
}
方法
Go中的方法是作用在特定类型的变量上,因此自定义类型都可以有方法,而不仅仅是struct。其定义为:func (receiver type) methodName(参数列表)(返回值列表){}。其中,我们是通过(recevier type)来访问type中的字段。在C++中,此会定义在结构体里面,然后public。
package main
import "fmt"
type Student struct {
Name string
Age int
Score int
}
func (p Student) init(name string, age int, score int) {
//通过(p Student)访问Student中的字段
//在C++中会定义在结构体里面,然后public
p.Name = name
p.Age = age
p.Score = score
fmt.Println(p)
}
func (p Student) get() Student {
return p
}
func main() {
var stu Student
stu.init("stu", 10, 200)
stu1 := stu.get()
fmt.Println(stu1)
}
此时,输出结果如下:但我们会发现一个问题,就是init没有生效。原因为:此时的p仅仅为stu的一个拷贝,解决此问题,我们得传进一个指针。
用指针换用如下代码即可
package main
import "fmt"
type Student struct {
Name string
Age int
Score int
}
func (p *Student) init(name string, age int, score int) {
//通过(p Student)访问Student中的字段
//在C++中会定义在结构体里面,然后public
p.Name = name
p.Age = age
p.Score = score
fmt.Println(p)
}
func (p Student) get() Student {
return p
}
func main() {
var stu Student
stu.init("stu", 10, 200)
stu1 := stu.get()
fmt.Println(stu1)
}
方法用于其他类型:
package main
import "fmt"
type integer int
func (p integer) print() {
fmt.Println("p is", p)
}
func (p integer) set(b integer) { //非指针
p = b
}
func (p *integer) set1(b integer) { //指针
*p = b
}
func main() {
var a integer
a = 100
a.print()
a.set(1000)
a.print() //输出仍然为100
a.set1(1000)
a.print() //输出为1000
}