标签:ide 软件 函数返回 面向对象语言 避免 薪资 peter 员工 自己的
1 、什么是结构体
GO语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
2、什么是实例化?
package main import "fmt" func main() { //实例化方式一 var stu1 Student fmt.Printf("stu1=%T,%v,%q \n", stu1, stu1, stu1) stu1.name = "zs" stu1.age = 12 stu1.sex = 1 fmt.Printf("stu1=%T,%v,%q \n", stu1, stu1, stu1) //实例化方式二 stu2 := Student{} stu2.name = "David" stu2.age = 33 stu2.sex = 1 fmt.Printf("stu2=%T,%v,%q \n", stu2, stu2, stu2) //实例化方式三 stu3 := Student{ name: "Josh", age: 28, sex: 1, } fmt.Printf("stu3=%T,%v,%q \n", stu3, stu3, stu3) //实例化四 stu4 := Student{"Ruby", 30, 0} fmt.Printf("stu3=%T,%v,%q \n", stu4, stu4, stu4) //实例化五 //使用内置函数new()对结构体进行实例化,结构体实例化后形成指针类型的结构体 //·new内置函数会分配内存。第一个参数是类型,而不是值,返回的值是指向该类型新分配的零值的指针。该函数用于创建某个类型的指针。 stu5 := new(Student) (*stu5).name = "Running" (*stu5).age = 31 stu5.sex = 0 //语法糖的方式 fmt.Printf("stu3=%T,%v,%q \n", stu5, stu5, stu5) //stu3=*main.Student,&{Running 31 0},&{"Running" ‘\x1f‘ ‘\x00‘} } //结构体的定义 type Student struct { name string age int sex int8 }
语法糖的概念( Syntactic sugar)
package main import "fmt" func main() { arr := [4]int{1, 2, 3, 4} arr2 := &arr fmt.Println((*arr2)[3]) //数组中的语法糖 fmt.Println(arr2[3]) //切片 arr3 := []int{10, 20, 30, 40} arr4 := &arr3 fmt.Println((*arr4)[3]) //切片中没有语法糖 //fmt.Println(arr4[3]) }
3、结构体是值类型传递
struct 默认是深拷贝
package main import "fmt" func main() { stu1 := Student{"zs", 18, 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1) //stu1:=main.Student,0xc0000044a0,{zs 18 0} stu2 := stu1 stu2.name = "ls" fmt.Printf("stu2:=%T,%p,%v \n", stu2, &stu2, stu2) //stu2:=main.Student,0xc000004520,{ls 18 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1) //stu1:=main.Student,0xc0000044a0,{zs 18 0} //修改stu2对stu1没有任何影响 }
实现浅拷贝
1、直接赋值指针地址
package main import "fmt" func main() { stu1 := Student{"zs", 18, 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1) //stu1:=main.Student,0xc00005a440,{zs 18 0} stu2 := &stu1 stu2.name = "ls" fmt.Printf("stu2:=%T,%p,%v \n", stu2, stu2, stu2) //stu2:=*main.Student,0xc00005a440,&{ls 18 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1) //stu1:=main.Student,0xc00005a440,{ls 18 0} //修改stu2对stu1有影响 }
2、实现结构体浅拷贝:通过new()函数来实例化对象
package main import "fmt" func main() { //3、实现结构体浅拷贝:通过new()函数来实例化对象 d4 := new(Dog) d4.name = "多多" d4.color = "棕色" d4.age = 1 d4.kind = "巴哥犬" d5 := d4 fmt.Printf("d4: %T , %v , %p \n", d4, d4, d4) //d4: *main.Dog , &{多多 棕色 1 巴哥犬} , 0xc000040080 fmt.Printf("d5: %T , %v , %p \n", d5, d5, d5) fmt.Println("--------------------------------------") d5.color = "金色" d5.kind = "金毛" fmt.Println("d5修改后:", d5) //d5修改后: &{多多 金色 1 金毛} fmt.Println("d4:", d4) //d4: &{多多 金色 1 金毛} } type Dog struct { name string color string age int8 kind string }
结构体对象或指针作为函数的参数及函数返回值
匿名结构体
//匿名结构体 addr := struct { province, city string }{"陕西省", "西安市"} fmt.Println(addr)
结构体的匿名字段
结构体中的字段没有名字,只包含一个没有字段名的类型。这些字段被称为匿名字段。
package main import "fmt" type User struct { string byte int8 float64 } func main() { // 实例化结构体 user:= User{"Steven" , ‘m‘ , 35 , 177.5} fmt.Println(user) //如果想依次输出姓名、年龄、身高、性别 fmt.Printf("姓名:%s \n" , user.string) fmt.Printf("身高:%.2f \n" , user.float64) fmt.Printf("性别:%c \n" , user.byte) fmt.Printf("年龄:%d \n" , user.int8) }
•将一个结构体作为另一个结构体的属性(字段),这种结构就是结构体嵌套。
•结构体嵌套可以模拟面向对象中的两种关系:
package main import "fmt" type Address struct { province, city string } type Person struct { name string age int address *Address } func main() { //模拟结构体对象之间的聚合关系 p := Person{} p.name = "Steven" p.age = 35 //赋值方式1: addr := Address{} addr.province = "北京市" addr.city = "海淀区" p.address = &addr fmt.Println(p) fmt.Println("姓名:", p.name) fmt.Println("年龄:", p.age) fmt.Println("省:", p.address.province) fmt.Println("市:", p.address.city) fmt.Println("-----------------------") //修改Person对象的数据,是否会影响Address对象的数据? p.address.city = "昌平区" fmt.Println("姓名:", p.name) fmt.Println("年龄:", p.age) fmt.Println("省:", p.address.province) fmt.Println("市:", p.address.city) fmt.Println("addr市:", addr.city) //?是否会受到影响? fmt.Println("-----------------------") //修改Address对象的数据,是否会影响Person对象的数据? addr.city = "大兴区" fmt.Println("姓名:", p.name) fmt.Println("年龄:", p.age) fmt.Println("省:", p.address.province) fmt.Println("市:", p.address.city) fmt.Println("addr市:", addr.city) //?是否会受到影响? fmt.Println("-----------------------") //赋值方式2 p.address = &Address{ province: "陕西省", city: "西安市", } fmt.Println(p) fmt.Println("姓名:", p.name) fmt.Println("年龄:", p.age) fmt.Println("省:", p.address.province) fmt.Println("市:", p.address.city) fmt.Println("-----------------------") }
•继承是传统面向对象编程中三大特征之一。用于描述两个类之间的关系。一个类(子类、派生类)继承于另一个类(父类、超类)。
•子类可以有自己的属性和方法,也可以重写父类已有的方法。
•子类可以直接访问父类所有的属性和方法。
•提升字段:
〇在结构体中属于匿名结构体的字段称为提升字段,因为它们可以被访问,就好像它们属于拥有匿名结构字段的结构一样。
〇换句话说,父类中的字段就是提升字段。
•继承的意义:避免重复代码、扩展类的功能
•采用匿名字段的形式就是模拟继承关系。而模拟聚合关系时一定要采用有名字的结构体作为字段
package main import ( "fmt" ) type Person struct { name string age int sex string } type Student struct { Person schoolName string } func main() { //1、实例化并初始化Person p1 := Person{"Steven", 35, "男"} fmt.Println(p1) fmt.Println("-------------------") //2、实例化并初始化Student // 写法1: s1 := Student{p1, "北航软件学院"} printInfo(s1) //写法2: s2 := Student{Person{"Josh", 30, "男"}, "北外高翻学院"} printInfo(s2) //写法3: s3 := Student{Person: Person{ name: "Penn", age: 19, sex: "男", }, schoolName: "北大元培学院", } printInfo(s3) // 写法4: s4 := Student{} s4.name = "Daniel" s4.sex = "男" s4.age = 12 s4.schoolName = "北京十一龙樾" printInfo(s4) } func printInfo(s1 Student) { fmt.Println(s1) fmt.Printf("%+v \n", s1) fmt.Printf("姓名:%s, 年龄:%d , 性别:%s ,学校:%s \n", s1.name, s1.age, s1.sex, s1.schoolName) fmt.Println("-------------------") }
• Go语言同时有函数和方法,方法的本质是函数,但是方法和函数又具有不同点。
1、 含义不同
•函数function是一段具有独立功能的代码,可以被反复多次调用,从而实现代码复用。而方法method是一个类的行为功能,只有该类的对象才能调用。
2、 方法有接受者,而函数无接受者
• Go语言的方法methods—种作用于特定类型变量的函数。这种特定类型变量叫做Receiver (接受者、接收者、接收器)。
•接受者的概念类似于传统面向对象语言中的this或self关键字。
• Go语言的接受者强调了方法具有作用对象,而函数没有作用对象。
•—个方法就是一个包含了接受者的函数。
• Go语言中,接受者的类型可以是任何类型,不仅仅是结构体,也可以是struct类型外的其他任何类型。
3、 函数不可以重名,而方法可以重名
•只要接受者不同,则方法名可以一样。
package main import "fmt" import "base" type Employee struct { name , currency string salary float64 } func main() { emp1 := Employee{"Daniel" , "$" , 2000} emp1.printSalary()//员工姓名:Daniel ,薪资:$2000.00 emp1.updateSalary(1000) emp1.printSalary()//员工姓名:Daniel ,薪资:$1000.00 } //printSalary方法 func (e Employee) printSalary() { fmt.Printf("员工姓名:%s ,薪资:%s%.2f \n", e.name , e.currency , e.salary) } func (e *Employee) updateSalary(num float64) { e.salary=num }
方法的继承与重写
package main import "fmt" import "base" type Human struct { name, phone string age int } type Student struct { Human school string } type Employee struct { Human company string } func main() { s1 := Student{Human{"Daniel", "15012345678", 13}, "十一龙樾"} e1 := Employee{Human{"Steven", "17812345678", 35}, "1000phone"} s1.printName() e1.printName() s1.SayHi() e1.SayHi() } //======================方法的继承============================= func (h *Human) printName() { fmt.Println("大家好!我是%s ", h.name) } //=====================方法的重写============================= func (h *Human) SayHi() { fmt.Printf("大家好!我是%s , 我%d岁 , 联系方式:%s \n", h.name, h.age, h.phone) } func (s *Student) SayHi() { fmt.Printf("大家好!我是%s , 我%d岁 , 我在%s上学,联系方式:%s \n", s.name, s.age, s.school, s.phone) } func (e *Employee) SayHi() { fmt.Printf("大家好!我是%s , 我%d岁 , 我在%s工作,联系方式:%s \n", e.name, e.age, e.company, e.phone) }
标签:ide 软件 函数返回 面向对象语言 避免 薪资 peter 员工 自己的
原文地址:https://www.cnblogs.com/jalja/p/11795509.html