Go 基础 02
- 结构体排序
1 package main 2 3 import ( 4 "fmt" 5 "math/rand" 6 "sort" 7 ) 8 9 type Student struct { 10 Name string 11 Id string 12 age int 13 } 14 15 type Book struct { 16 Name string 17 Author string 18 } 19 20 // 通过接口实现标准库中 sort 的 Sort 方法 21 // 定义一个 Student 类型的切片,名字叫 StudentArray 22 type StudentArray []Student 23 24 // 返回 Student 类型的切片长度 25 func (p StudentArray) Len() int { 26 return len(p) 27 } 28 29 // 返回 Student 类型的切片 i j 位置姓名字符串比较的结果 30 func (p StudentArray) Less(i, j int) bool { 31 // 从大到小排序 32 // return p[i].Name > p[j].Name 33 // 从小到大排序 34 return p[i].Name < p[j].Name 35 } 36 37 // 交换 i j 位置 38 func (p StudentArray) Swap(i, j int) { 39 p[i], p[j] = p[j], p[i] 40 } 41 42 func main() { 43 var stus StudentArray 44 // 向 StudentArray 中赋值 45 for i := 0; i < 10; i++ { 46 stu := Student{ 47 Name: fmt.Sprintf("stu%d", rand.Intn(100)), 48 Id: fmt.Sprintf("110%d", rand.Intn(100)), 49 age: rand.Intn(100), 50 } 51 stus = append(stus, stu) 52 } 53 // 遍历 StudentArray 并打印值 54 for _, v := range stus { 55 fmt.Println(v) 56 } 57 fmt.Println() 58 // 排序 59 sort.Sort(stus) 60 // 遍历 StudentArray 并打印值 61 for _, v := range stus { 62 fmt.Println(v) 63 } 64 }
- 通用链表
1 // link.go 2 3 package main 4 5 import ( 6 "fmt" 7 ) 8 9 // 通用链表 10 // 链表中的一个节点 11 type LinkNode struct { 12 // 空接口(任何类型都已经实现空接口) 13 // 也就是任何类型的变量都可以赋值给空接口 14 data interface{} 15 // 指向后面节点的指针 16 next *LinkNode 17 } 18 19 // 链表 20 type Link struct { 21 // 指向头节点的指针 22 head *LinkNode 23 // 指向尾节点的指针 24 tail *LinkNode 25 } 26 27 // 节点从头部插入 28 func (p *Link) InsertHead(data interface{}) { 29 // 生成新的节点 30 node := &LinkNode{ 31 data: data, 32 next: nil, 33 } 34 35 // 当头指针和尾指针都为空时,表示此时的链表为空链表 36 if nil == p.tail && nil == p.head { 37 p.tail = node 38 p.head = node 39 return 40 } 41 42 // 新的节点的 next 要等于头节点 43 node.next = p.head 44 // 更新头部指针,使头部指针重新指向新的节点 45 p.head = node 46 47 } 48 49 // 节点从尾部插入 50 func (p *Link) InsertTail(data interface{}) { 51 // 生成新的节点 52 node := &LinkNode{ 53 data: data, 54 next: nil, 55 } 56 // 当头指针和尾指针都为空时,表示此时的链表为空链表 57 if nil == p.tail && nil == p.head { 58 p.tail = node 59 p.head = node 60 return 61 } 62 63 // 之前尾部节点的 next 指向新的节点 64 p.tail.next = node 65 // 更新尾部指针,指向新节点 66 p.tail = node 67 } 68 69 // 遍历链表 70 func (p *Link) Trans() { 71 q := p.head 72 for nil != q { 73 fmt.Println(q.data) 74 q = q.next 75 } 76 }
1 // main.go 2 3 package main 4 5 import ( 6 "fmt" 7 ) 8 9 func main() { 10 var headLink Link 11 // 从头部插入10个节点(逆序) 12 for i := 0; i < 10; i++ { 13 headLink.InsertHead(fmt.Sprintf("crixus_%d", i)) 14 } 15 headLink.Trans() 16 fmt.Println() 17 var tailLink Link 18 // 从尾部插入10个节点(顺序) 19 for i := 0; i < 10; i++ { 20 tailLink.InsertTail(fmt.Sprintf("crixus_%d", i)) 21 } 22 tailLink.Trans() 23 }
- 通过反射操作结构体
1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 ) 8 9 type Student struct { 10 Name string `json:"student_name"` 11 Age int 12 Score float32 13 Sex string 14 } 15 16 func (s Student) Print() { 17 fmt.Println(s) 18 } 19 20 func (s Student) Set(name string, age int, score float32, sex string) { 21 s.Name = name 22 s.Age = age 23 s.Score = score 24 s.Sex = sex 25 } 26 27 // 通过反射操作结构体 28 func TestStruct(a interface{}) { 29 // 获取指定字段的 tag 标签 30 typ := reflect.TypeOf(a) 31 tag := typ.Elem().Field(0).Tag.Get("json") 32 fmt.Printf("tag => %s\n", tag) 33 34 // 获取指定字段的 name 标签 35 name := typ.Elem().Field(1).Name 36 fmt.Printf("name => %s\n", name) 37 38 val := reflect.ValueOf(a) 39 // 获取类别 40 kd := val.Kind() 41 // 当类别不为结构体,就不再进行分析,直接退出 42 if reflect.Ptr != kd && reflect.Struct == val.Elem().Kind() { 43 fmt.Println("not struct ...") 44 return 45 } 46 // 获取结构体中字段的数量 47 num := val.Elem().NumField() 48 fmt.Printf("struct has %d fields\n", num) 49 50 // 修改结构体中指定字段的值 51 val.Elem().Field(0).SetString("crixus") 52 53 // 遍历结构体中字段的值 54 for i := 0; i < num; i++ { 55 fmt.Printf("Field %d : Kind %v : %v => %v\n", i, val.Elem().Field(i).Kind(), typ.Elem().Field(i).Name, val.Elem().Field(i)) 56 } 57 58 // 获取结构体中方法的数量 59 numOfMethod := val.Elem().NumMethod() 60 fmt.Printf("struct has %d method\n", numOfMethod) 61 62 // 调用结果体中的方法 63 var params []reflect.Value 64 val.Elem().Method(0).Call(params) 65 } 66 67 func main() { 68 var a Student = Student{ 69 Name: "stu01", 70 Age: 18, 71 Score: 92.5, 72 Sex: "female", 73 } 74 // 通过 json 打包结构体 75 // result 是字节数组 76 result, _ := json.Marshal(a) 77 // 输出时,result 字节数组转字符串 78 fmt.Println("Json result =>", string(result)) 79 TestStruct(&a) 80 }
- 文件拷贝
1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 ) 8 9 func main() { 10 11 // 相对路径 12 _, err := CopyFile("target.txt", "source.txt") 13 if nil != err { 14 fmt.Println("Copy failed ...", err) 15 return 16 } 17 fmt.Println("Copy done ...") 18 } 19 20 // 文件拷贝 21 func CopyFile(dstName, srcName string) (written int64, err error) { 22 // 读文件 23 src, err := os.Open(srcName) 24 if nil != err { 25 return 26 } 27 defer src.Close() 28 29 // 写文件 30 dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644) 31 if nil != err { 32 return 33 } 34 defer dst.Close() 35 36 return io.Copy(dst, src) 37 }
- 结构体序列化和反序列化
1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 ) 7 8 type User struct { 9 UserName string `json:"username"` 10 NickName string 11 Age int 12 Birthday string 13 Sex string 14 Email string 15 Phone string 16 } 17 18 func testStruct() (ret string, err error) { 19 user1 := &User{ 20 UserName: "user01", 21 NickName: "Crixus01", 22 Age: 18, 23 Birthday: "2019-02-12", 24 Sex: "male", 25 Email: "280247844@qq.com", 26 Phone: "12345678901", 27 } 28 29 // json.Marshal 执行后返回字节数组 30 data, err := json.Marshal(user1) 31 if nil != err { 32 err = fmt.Errorf("json.marshal failed, err :", err) 33 return 34 } 35 // 字节数组转为字符串 36 ret = string(data) 37 return 38 } 39 40 // json 串反序列化为结构体 41 func test() { 42 data, err := testStruct() 43 if nil != err { 44 fmt.Println("test struct failed ...") 45 } 46 var user1 User 47 // 字符串转为字符串字节数组 48 // 结构体是值类型,要更新其中字段需要传地址进去 49 err = json.Unmarshal([]byte(data), &user1) 50 if nil != err { 51 fmt.Println("Unmarshal failed ...") 52 } 53 fmt.Println(user1) 54 } 55 56 func main() { 57 // json 串反序列化为结构体 58 test() 59 }
( Over )