结构体
Go语言中的结构体(
struct
)相当于Java
的class
、JavaScript
的class
等,也就是所谓的对象。方法:也就是在函数的关键字和方法名中间加入一个特殊的接收器类型,接收器可以是结构体也可以不是,接收器是可以内部访问的。
// 命名结构体 type Lesson struct { name string //课程名称 scores int //课程分数 time int //课程时间 } //给课程绑定一个方法 func (l Lesson) ShowLessonInfo() { //结构体的'方法' 常用 fmt.Println("name:", l.name) fmt.Println("time:", l.time) } func main() { //创建结构体时,使用字段名称对每个字段进行初始化 lesson0 := Lesson{ name: "lesson0", scores: 1, time: 20, } lesson0.ShowLessonInfo() lesson1 := Lesson{"lesson1", 2, 30} lesson1.ShowLessonInfo() } //这下就可能会有疑惑:为什么有了函数又要有方法这种东西? //因为Go语言中因为相同名字的方法可以定义在不同的类型上,而相同名字的函数式不被允许的。 /* 例如func (author Author) PrintfInfo(){...} 与 func (lesson Lesson) PrintfInfo(){...} 这两个同名函数是不冲突的,因为属于不同方法 */
组合:例如有一些课程,它们同属于一个班级。那么这些课程就会有这个班级的一些属性。(在其他的语言里这个叫继承,但因为Go语言没有类的概念,所以就不是这个叫法,本质上也有一定的区别)
另外:组合也不止能组合一个,可以是多组合,例如猫是动物,也是好朋友,这下猫就可以组合这两个结构体。
// 命名结构体 type Lesson struct { Class //Lesson组合了Class,其实说是继承也对 name string //课程名称 scores int //课程分数 time int //课程时间 } type Class struct { name string //班级名称 } func (l Lesson) classInfo() { fmt.Printf("班级:%s 名字:%s\n", l.Class.name, l.name) } func main() { class0 := Class{"计算机一班"} lesson0 := Lesson{ Class: class0, name: "高数", scores: 1, time: 20, } lesson0.classInfo() }
结构体指针:和常见的变量指针差不多,例如我要修改课程的名字,如果不使用指针的话,即便方法里写了修改,输出出来还是没修改的值。(详情请看函数篇里有说明为什么,与存放在内存的地址有关)
简短一点就是:指针接收器能改变值,而值接收器不能改变。(和c++的函数指针、引用几乎差不多一个意思,与封装性有关)
// 命名结构体 type Lesson struct { Class //Lesson组合了Class name string //课程名称 scores int //课程分数 time int //课程时间 } type Class struct { name string //班级名称 } func (l Lesson) classInfo() { fmt.Printf("班级:%s 名字:%s\n", l.Class.name, l.name) } func (l *Lesson) setName(name string) { //(l lesson)不行,得用指针才能实现修改 l.name = name } func main() { class0 := Class{"计算机一班"} lesson0 := Lesson{ Class: class0, name: "高数", scores: 1, time: 20, } lesson0.classInfo() lesson0.setName("线性代数") lesson0.classInfo() } //输出:班级:计算机一班 名字:高数 // 班级:计算机一班 名字:线性代数
- 另外有指针方法又有常规方法会出现警告,如果想要消除警告,给全部的方法加上指针变为指针方法就行了,但也相对的会作用于原有的对象。
tag:例如在和
Json
一起使用里面,tag就会很常见到。type Lesson struct { Class //Lesson组合了Class Name string `json:"name"` //课程名称 Scores int `json:"scores"` //课程分数 Time int `json:"time"` //课程时间 } //但是如果我觉得结构体里面有敏感属性,不想让json转译出来,那么可以像下面这样做 type Lesson0 struct { Class Name string `json:"name"` Scores int `json:"-"` //这样用-去表示,就不会被json转译出来了。 Time int `json:"time"` } //还有例如我没有定义Lesson里面的Score,但它被用时会默认给对应的零值,如果有需求不想让它变零值,可以像下面这样做。 type Lesson1 struct { Class Name string `json:"name,omitempty"` //这样就会忽略Name的零值直接变为空。 Scores int `json:"-"` //这样用-去表示,就不会被json转译出来了,这个相当于忽略字段。 Time int `json:"time"` } func main() { class0 := Class{"计算机一班"} lesson0 := Lesson{ Class: class0, Name: "高数", Scores: 1, Time: 20, } byteData, _ := json.Marshal(lesson0) fmt.Println(string(byteData)) //输出:{"name":"高数","scores":1,"time":20} //输出的是一个非常标准的json,但是你会发现,这段json里面的key都是tag所表示的名字。这就是tag的用法。 } //这里面的``内的内容就是tag
- 另外,并不是只有在结构体上才可以调用方法,在非结构体上也可以调用方法。
评论(0)