Golang map集合丶struct结构体丶继承
一.map集合
1 // map键值对集合 2 func testMap() { 3 // Map的定义: var 变量名 map[keytType]valueType 4 // 细节: 5 // 1.key唯一 6 // 2.map是引用 7 // 3.直接遍历map是无序的 8 // 4.map会自动扩容,make中设置的长度并没有对map任何限制 9 var m1 = make(map[string]int32, 2) 10 var m2 = map[string]string{ 11 "key1": "test1", 12 "key2": "test2", 13 "key3": "test3", 14 } 15 m2["key4"] = "test4" 16 delete(m2, "key2") // 删除操作.如果要删除所有,需要循环删除,或者重新定义后让回收机制回收 17 fmt.Println("m1=", m1) 18 fmt.Println("m2=", m2) 19 20 // 查找 21 val, b := m2["key4"] 22 fmt.Println("=", val, " ", b) // = test4 true 23 fmt.Println("=", m2["key4"]) // = test4 24 25 fmt.Println("================================") 26 // 遍历 第一次 27 for key, val := range m2 { 28 fmt.Println("key=", key, " val=", val) 29 } 30 m2["key5"] = "test5" 31 fmt.Println("===========可以看到map遍历的顺序并不是每次都一样,特别是在新加了元素之后=====================") 32 // 遍历 第二次 33 for key, val := range m2 { 34 fmt.Println("key=", key, " val=", val) 35 } 36 fmt.Println("================================") 37 fmt.Println("===========如果要按固定排序输出的话只能通过keys数组切片去实现顺序输出=====================") 38 var mapIndexs = make([]string, len(m2)) 39 temIndex := 0 40 for k, _ := range m2 { 41 mapIndexs[temIndex] = k 42 temIndex++ 43 } 44 sort.Strings(mapIndexs) 45 for _, k := range mapIndexs { 46 fmt.Println(m2[k]) 47 } 48 fmt.Println("================================") 49 // 集合切片 50 var m3 = make([]map[string]string, 2) 51 m3[0] = map[string]string{ 52 "name": "张三", 53 "age": "20", 54 } 55 m3[1] = map[string]string{ 56 "name": "李四", 57 "age": "19", 58 } 59 w5 := map[string]string{ 60 "name": "王五", 61 "age": "21", 62 } 63 m3 = append(m3, w5) 64 fmt.Printf("%v &m3[0]=%x &m3[1]=%x \n", m3, &(m3[0]), &(m3[1])) 65 66 }
二.struct结构体
1 type Person1 struct { 2 Name string 3 Age int16 // 小写开头带表只能本包可用 4 } 5 6 func (self *Person1) PrintInfo() (result bool) { 7 self.Name = "张三丰" 8 fmt.Println("姓名:", self.Name, "\t年龄:", self.Age) 9 result = true 10 return 11 } 12 13 // 定义struct方法并不会影响内存分配 14 func (self Person1) PrintInfo1() { 15 self.Name = "张三丰" // 这里并不会修改调用对象 16 fmt.Println("姓名:", self.Name, "\t年龄:", self.Age) 17 } 18 19 // 给结构体实现String() 那进行强制str转换的时候就是调用这个 20 func (self *Person1) String() string { 21 return fmt.Sprintln("姓名:", self.Name, "\t年龄:", self.Age) 22 } 23 24 func testStruct() { 25 fmt.Println("=======================struct定义丶访问============================") 26 type Person struct { 27 Name string 28 age int16 // 本包可用 29 } 30 var p1 Person = Person{Name: "Tom", age: 19} 31 var p2 *Person = new(Person) 32 var p3 *Person = &Person{Name: "Lisa", age: 22} 33 p4 := p1 34 p4.Name = "Jerry11" 35 p1.age = 19 36 p2.age = 99 // 因p2是指针,编译器会将"p2.age = 99" 同等 "(*p2).age = 99" 37 fmt.Println("struct 是值类型,并非引用:", p1, p2, p3, p4) 38 fmt.Println("占用内存大小:", unsafe.Sizeof(p1.Name)) 39 fmt.Println("占用内存大小:", unsafe.Sizeof(p4.Name)) 40 fmt.Println() 41 fmt.Println("============================使用细节===================================") 42 // 1.属性名小写,只能在本包中访问 43 // 2.指针: "*p2.age = 99" 中的"."优先级高于"*" 所以必须"(*p2.age) = 99" 或者不用"*" 44 // 3.结构体中的属性,内存分配是连续的. 45 // 4.不同struct类型变量如果要强制转换的话,必须声明定义的属性字段类型顺序相同 46 // 5.struct中提供tag来协助序列与反序列转化(struct转json或反过来[反射]) 47 type Monster struct { 48 Name string `json:"name"` 49 Age int16 `json:"age"` 50 Skill string `json:"skill"` 51 } 52 m1 := Monster{"关羽", 101, "大宝剑"} 53 jsonstr, _ := json.Marshal(m1) // 如果将属性首字母改称小写,在这里json包中就访问不到了.所以就需要用到tag了 54 fmt.Println(string(jsonstr)) 55 fmt.Println() 56 fmt.Println("============================struct 方法 ===================================") 57 // 定义语法:func (self Person1) PrintInfo() (result bool) { 58 // 注意细节: 59 // 1.给struct定义方法并不会影响struct内存分配 60 // 2.首参为指针类型的时候才是self,不然self只是值传递 61 // 3.语法中的Person1类型,并不一定要是struct,可以是任何自定义类型 62 // 4.给结构体实现String()方法 那进行Println输出的时候就是调用这个 63 p5 := Person1{"Carry", 30} 64 fmt.Println(unsafe.Sizeof(p5)) 65 p5.PrintInfo() // 同等:(&p5).PrintInfo() 注意:不管你这里从"(&p5)."还是"p5."来调用,编译器都会去设配结构体"PrintInfo()"方法的定义去设配 66 fmt.Println("Println:", &p5) 67 68 fmt.Println() 69 fmt.Println("============================struct 工厂模式 ===================================") 70 // 工厂模式:定义的结构体为私有的,外部想要获得,只能通过工厂统一创建初始化(具体代码看student包) 71 stu1 := student.StudentFactory("三年级(2)班", "陈是凯", 13, 85) 72 fmt.Println(stu1) 73 stu2 := student.HighStudentFactory("三年级(1)班", "吴开军", 26, 75, 74 "打篮球", 9, 2002, 1, 15, 75 178) 76 fmt.Println(stu2) 77 78 }
三.struct继承
1 package student 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 // 工厂模式:struct结构体为私有的,通过工厂方法返回结构体变量 9 func HighStudentFactory(classID string, name string, age int8, score int16, 10 hobby string, hobbyScore int16, 11 byear uint16, bmonth uint16, bday uint16, 12 heightCM uint16) (result *HighStudent) { 13 14 result = &HighStudent{ 15 Person: Person{ClassID: classID, Name: name, Age: age, score: score}, 16 Hobby: Hobby{Name: hobby, score: hobbyScore}, 17 Birthday: Birthday{Year: byear, Month: bmonth, Day: bday}, 18 HeightCM: 172, 19 } 20 21 return 22 } 23 24 /* student结构体在factory文件中. 这样重新定义类型,原来student的方法并不会跟过来 */ 25 type Person student 26 27 /* 但是这样继承,原来student的方法会跟过来 */ 28 type Person1 struct { 29 student 30 } 31 32 type Hobby struct { 33 Name string 34 score int16 35 } 36 37 type Birthday struct { 38 Year uint16 39 Month uint16 40 Day uint16 41 } 42 43 /* 正常项目不要用这种多重继承方式,会严重干扰你的思绪 */ 44 type HighStudent struct { 45 Person // 继承 46 Hobby // 继承 47 Birthday // 继承 48 HeightCM uint16 49 } 50 51 func (self *Hobby) String() string { 52 return self.Name + "\t热度:" + strconv.Itoa(int(self.score)) 53 } 54 55 func (self *Birthday) String() string { 56 return fmt.Sprintf("%d年%d月%d日", self.Year, self.Month, self.Day) 57 } 58 59 func (self *HighStudent) String() string { 60 s1 := student(self.Person).String() // 因为Person和student完全一样所以可以直接强制转换 61 s2 := self.Birthday.String() 62 s3 := self.Hobby.String() 63 return fmt.Sprintf("%v\n生日:%v\n身高:%v\n爱好:%v\n", s1, s2, self.HeightCM, s3) 64 } 65 66 func TestAddress() { 67 stu1 := Person1{student{"八年级(2)班", "五栋梁", 25, 99}} 68 69 fmt.Println(stu1.GetScoreRate()) 70 }