数据类型
字符串
字符串常用系统函数
字符串循环,长度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//计算长度 func s1() { s := "我爱go语言" fmt.Println("字节长度", len(s)) fmt.Println("...") len := 0 //遍历字符串 for i, ch := range s { fmt.Printf("%d:%c ", i, ch) len++ } fmt.Printf(" 字符串长度:%d", len) //遍历所有字节 for i, ch := range []byte(s) { fmt.Printf("%d:%x ", i, ch) } //遍历所有字符 count := 0 for i, ch := range []rune(s) { fmt.Printf("%d:%c ", i, ch) count++ } //字符长度 fmt.Println("len=", count) fmt.Println("len=", utf8.RuneCountInString(s)) }
strings使用 截取,大小写等
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//是否包含子串 func s2() { fmt.Println(strings.Contains("seafood", "foo")) } //判断字符串是否包含另一字符串的任一字符 func s3() { fmt.Println(strings.ContainsAny("second", "one")) } //判断字符串是否包含unicode码值 func s4() { fmt.Println(strings.ContainsRune("一丁丐", '丁')) fmt.Println(strings.ContainsRune("一丁丐", 19969)) var st int = '丁' fmt.Printf("%v", st) //19969 } //返回字符串包含另一字符串的个数 func s5() { fmt.Println(strings.Count("google", "o")) } //判断字符串s是否有前缀字符串 func s6() { fmt.Println(strings.HasPrefix("1000phone", "1000")) fmt.Println(strings.HasPrefix("1000phone", "PHONE")) } //判断字符串是否有后缀字符串 func s7() { fmt.Println(strings.HasSuffix("1000phone news", "news")) fmt.Println(strings.HasSuffix("1000phone news", "new")) } //判断字符串中另一字符串首次出现的位置 func s8() { fmt.Println(strings.Index("hello world", "o")) //4 } func s9() { fmt.Println(strings.IndexAny("abcABCDF", "教育基地A")) //3 } //返回字符串中字符首次出现的位置 func s10() { fmt.Println(strings.IndexByte("123abc", 'a')) } //判断字符串是否包含unicode值 func s11() { fmt.Println(strings.IndexRune("abcABC", 'C')) fmt.Println(strings.IndexRune("abcABC", 'g')) //-1 } //返回字符串中函数f(r)=true手册出现的位置 func s12() { f := func(c rune) bool { //判断是否为中文 return unicode.Is(unicode.Han, c) } fmt.Println(strings.IndexFunc("hello123,中国", f)) //9 } //返回字符串中子串最后一次出现的位置 func s13() { fmt.Println(strings.LastIndex("google", "o")) } //字符串切割为切片 func s14() { str := "abc.jpg" s1 := strings.Split(str, ".") fmt.Println(s1[len(s1)-1]) } //字符串切割 //将字符串以空格分隔 func s15() { fmt.Println(strings.Fields("I have a dog")) } //将字符串以满足f(r)=true的字符分隔,返回一个切片 func s16() { f := func(c rune) bool { //返回非字符,非数字 return !unicode.IsLetter(c) && !unicode.IsNumber(c) } fmt.Println(strings.FieldsFunc("abc@2323#ewffw", f)) } //将字符串以sep作为分隔符进行切割,分隔后最后去掉sep func s17() { fmt.Printf("%q ", strings.Split("a,b,c", ",")) fmt.Printf("%q ", strings.Split("a man a plan a cannel", "a")) fmt.Printf("%q ", strings.Split("xyz", "")) fmt.Printf("%q ", strings.Split("", "bern")) fmt.Printf("%q ", strings.SplitN("a,b,c", ",", 2)) fmt.Printf("%q ", strings.SplitN("bern", "", 2)) } //分割后附上sep func s18() { fmt.Println(strings.SplitAfter("a,b,c", ",")) } //大小转化 //字符串每个单词首字母大写 func s19() { fmt.Println(strings.Title("her royal highness")) } //将字符串转大写 func s20() { fmt.Println(strings.ToTitle("louD noises")) } //转小写 func s21() { fmt.Println(strings.ToLower("I have a Dog")) } //字符串转成大写返回 func s22() { fmt.Println(strings.ToUpper("I have a Dog")) } //修剪字符串 //将字符串s首位包含在cutset中的任一字符去掉返回 func s23() { fmt.Println(strings.Trim(" steven wang ", " ")) } //将字符串s首尾满足函数f(r)=true 的字符去掉 func s24() { f := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) } //去除非字符和数字 fmt.Println(strings.TrimFunc("!@steven@$#hello@#@", f)) } //清除左侧字符 func s25() { fmt.Print(strings.TrimLeft(" sddddddg ", " ")) fmt.Print(strings.TrimRight(" sddddddg ", " ")) fmt.Print("aa") } // //将字符串s首尾满足函数f(r)=true 的字符去掉 func s26() { f := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) } //去除非字符和数字 fmt.Println(strings.TrimLeftFunc("!@steven@$#hello@#@", f)) fmt.Println(strings.TrimRightFunc("!@steven@$#hello@#@", f)) } //去除首尾空格 func s27() { fmt.Println(strings.TrimSpace(" a lone gopher ")) } //去除前缀 func s28() { s := "Goodbye,world" fmt.Println(strings.TrimPrefix(s, "Goodbye")) fmt.Println(strings.TrimSuffix(s, "world")) } //比较字符串大小 func s29() { fmt.Println(strings.Compare("abc", "cde")) fmt.Println("abc" < "cde") } //两个utf8字符串是否相等 func s30(){ fmt.Println(strings.EqualFold("Go","go")) } //将字符串重复n次返回 func s31(){ fmt.Println(strings.Repeat("abc",3)) } //字符串替换 func s32(){ fmt.Println(strings.Replace("jack rose","e","r",-1)) } //切片转字符串 func s33(){ s:=[]string{ "abc", "ABC", "123", } fmt.Println(strings.Join(s,",")) }
strconv使用 字符串相关的类型转换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//字符串转为其他类型 //字符串转int func s34(){ a,_:=strconv.Atoi("100") fmt.Printf("%T,%v ",a,a) } //解释给定基数的字符串s,并返回相应的值i func s35(){ //转为10进制 num,_:=strconv.ParseInt("-4e00",16,64) fmt.Printf("%T,%v ",num,num) //转10进制 num,_=strconv.ParseInt("01100001",2,64) fmt.Printf("%T,%v ",num,num) //输出二进制 num,_=strconv.ParseInt("-01100001",10,64) fmt.Printf("%T,%v ",num,num) //输出 num,_=strconv.ParseInt("4e00",16,64) fmt.Printf("%T,%v ",num,num) //输 num,_=strconv.ParseInt("5778",10,64) fmt.Printf("%T,%v ",num,num) } //转为无符号类型 func s36(){ //转为10进制 num,_:=strconv.ParseUint("-4e00",16,64) fmt.Printf("%T,%v ",num,num) //转10进制 num,_=strconv.ParseUint("01100001",2,64) fmt.Printf("%T,%v ",num,num) //输出二进制 num,_=strconv.ParseUint("-01100001",10,64) fmt.Printf("%T,%v ",num,num) //输出 num,_=strconv.ParseUint("4e00",16,64) fmt.Printf("%T,%v ",num,num) //输 num,_=strconv.ParseUint("5778",10,64) fmt.Printf("%T,%v ",num,num) } //将字符串s转换为float类型 func s37(){ pi:="3.1415926" num,_:=strconv.ParseFloat(pi,64) fmt.Printf("%T,%v ",num,num+2) fmt.Println("----------") } //字符串转bool类型 func s38(){ flag,_:=strconv.ParseBool("false") fmt.Printf("%T,%v ",flag,flag) fmt.Println("------") }
format使用 字符串相关的类型转换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//将其他类型格式化为字符串 //int转为字符串 func f1(){ s:=strconv.Itoa(199) fmt.Printf("%T,%v,len=%d ",s,s,len(s)) } //返回给定基数的i的字符串表示 func f2(){ s:=strconv.FormatInt(-19968,16) s=strconv.FormatInt(-40869,16) fmt.Printf("%T,%v,len=%d ",s,s,len(s)) } //返回给定基数的i的字符串表示,无符号 func f3(){ s:=strconv.FormatUint(19968,16) s=strconv.FormatUint(40869,16) fmt.Printf("%T,%v,len=%d ",s,s,len(s)) } //将浮点数转为字符串 func f4(){ s:=strconv.FormatFloat(3.1415926,'g',-1,64) fmt.Printf("%T,%v,len=%d",s,s,len(s)) } func main() { f4() }
常量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" ) func main() { var num int num = 9 //ok //常量声明的时候,必须赋值。 const tax int = 0 //常量是不能修改 //tax = 10 fmt.Println(num, tax) //常量只能修饰bool、数值类型(int, float系列)、string 类型 //fmt.Println(b) const ( a = iota b c d ) fmt.Println(a, b, c, d) }
数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" //定义长度为三的数组 //数组的长度一旦定义不可修改 //长度是数组类型的一部分 //二维数组 func a5() { a := [3][2]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } fmt.Println(a) fmt.Println(a[2][1]) } //数组的遍历 func a4() { var a = [...]string{"北京", "上海", "深圳"} for i := 0; i < len(a); i++ { fmt.Println(a[i]) } } //指定索引初始化数组 func a3() { a := []int{1: 1, 3: 5} fmt.Println(a) fmt.Printf("%T ", a) } func a2() { var testArray [3]int var numArray = []int{1, 2} //自行推断数组长度 var cityArray = [...]string{"北京", "上海", "深圳"} fmt.Println(testArray) fmt.Println(numArray) fmt.Println(cityArray) fmt.Printf("%T ", cityArray) } func main1() { var testArray [3]int var numArray = [3]int{1, 2} var cityArray = [3]string{"北京", "上海", "深圳"} fmt.Println(testArray) fmt.Println(numArray) fmt.Println(cityArray) } //二位数组只有第一层可以使用... func modif1(x [3]int) { x[0] = 100 } func modif2(x [3][2]int) { x[2][0] = 100 } func a6() { a := [3]int{10, 20, 30} modif1(a) fmt.Println(a) b := [3][2]int{ {1, 1}, {1, 1}, {1, 1}, } modif2(b) fmt.Println(b) } //求数组[1, 3, 5, 7, 8]所有元素的和 func arr7() { a := [5]int{1, 3, 5, 7, 8} var lg int = len(a) sum :=0 for i := 0; i < lg; i++ { sum += a[i] fmt.Println(a[i]) } fmt.Println(sum) }
示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" import "math/rand" import "time" func a1() { var intArr [3]int //数组定以后每个元素的地址为0 //地址占用八个字接 fmt.Println(intArr) intArr[0] = 10 intArr[1] = 20 intArr[2] = 30 fmt.Println(intArr) fmt.Printf("intArr地址%p intArr[0]地址%p intArr[1]地址%p ,intArr[2]地址%p", &intArr, &intArr[0], &intArr[1], &intArr[2]) fmt.Printf("类型%T", intArr[1]) } //for-range遍历数组 func a2() { //长度填...表示自动推导,但不可为空 heroes := [...]string{"宋江", "吴用", "卢俊义"} for i, v := range heroes { fmt.Printf("i=%v, v=%v ", i, v) } } //数组可以采用内存调用速度更快 //数组属于值类型,因此会进行值拷贝 //修改数组,采用引用传值 func a3(arr *[3]int) { //数组【下标】 (*arr)[0] = 99 } //创建一个byte类型,的26个元素的数组,分别放A-Z,并打印 func a4() { var myChars [26]byte for i := 0; i < 26; i++ { //i类型转换并相加 myChars[i] = 'A' + byte(i) } for i := 0; i < 26; i++ { fmt.Printf("%c-%v ", myChars[i], myChars[i]) } } //求数组中最大值 func a5() { var intArr [6]int = [...]int{1, -1, 9, 90, 11, 98000} maxVal := intArr[0] maxValIndex := 0 for i := 1; i < len(intArr); i++ { if maxVal < intArr[i] { maxVal = intArr[i] maxValIndex = i } } fmt.Printf("maxVal=%v maxValIndex=%v", maxVal, maxValIndex) } //求数组平均值 func a6() { var intArr2 [5]int = [...]int{1, -1, 9, 90, 12} sum := 0 for _, v := range intArr2 { sum += v } fmt.Printf("sum=%v,avg=%v", sum, float64(sum)/float64(len(intArr2))) } //生成五个随机数,并反转打印 func a7() { var intArr3 [5]int len := len(intArr3) rand.Seed(time.Now().UnixNano()) for i := 0; i < len; i++ { intArr3[i] = rand.Intn(100) } fmt.Println("交换前=", intArr3) temp := 0 for i := 0; i < len/2; i++ { temp = intArr3[len-1-i] intArr3[len-1-i] = intArr3[i] intArr3[i] = temp } fmt.Println("交换后=", intArr3) } func main() { a6() }
排序与查找
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" ) //冒泡排序 func BubbleSort(arr *[5]int) { fmt.Println("排序前arr=", (*arr)) for i := 0; i < len(*arr)-1; i++ { for j := 0; j < len(*arr)-1-i; j++ { if (*arr)[j] > (*arr)[j+1] { //交换 (*arr)[j], (*arr)[j+1] = (*arr)[j+1], (*arr)[j] } } } } //顺序查找 func s1() { names := [4]string{"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"} var heroName = "" fmt.Println("请输入要查找的人名") fmt.Scanln(&heroName) //方式一 //for i := 0; i < len(names); i++ { // if heroName == names[i] { // fmt.Printf("找到%v,下标%v ", heroName,i) // break // } else if i == (len(names) - 1) { // fmt.Printf("没有找到%v ", heroName) // } // //} //方式二:分两步处理 index:= -1 for i := 0; i < len(names); i++ { if heroName == names[i] { index = i break } } if index != -1 { fmt.Printf("找到%v, 下标%v ", heroName, index) } else { fmt.Println("没有找到", heroName) } } //二分法查找 func BinaryFind(arr *[6]int,leftIndex int,rightIndex int,findVal int){ //判断leftIndex是否大于rightIndex if leftIndex>rightIndex{ fmt.Println("找不到") return } //先找到中间下标 middle:=(leftIndex+rightIndex)/2 if(*arr)[middle]>findVal{ //要查找的值在leftIndex--middle中 BinaryFind(arr,leftIndex,rightIndex,findVal) }else if (*arr)[middle]<findVal{ BinaryFind(arr,middle+1,rightIndex,findVal) }else{ fmt.Printf("找到了,下表为%v ",middle) } } func main() { // arr := [5]int{24, 69, 80, 57, 13} // BubbleSort(&arr) // fmt.Println("main arr=", arr) //s1() arr:=[6]int{1,8,10,89,1000,1234} BinaryFind(&arr,0,len(arr)-1,1234) }
二维数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 二维数组 */ func a8() { var arr [4][6]int arr[1][2] = 1 arr[2][1] = 2 arr[2][3] = 3 for i := 0; i < 4; i++ { for j := 0; j < 6; j++ { // fmt.Print(arr[i][j], " ") //打印内存地址 fmt.Printf("%p ",&arr[i][j]) } fmt.Println() } } //内存地址分析 func a9() { //先声明后赋值 var arr2 [2][3]int arr2[1][1] = 10 fmt.Println(arr2) fmt.Printf("arr2[0]的地址%p ", &arr2[0]) fmt.Printf("arr2[1]的地址%p ", &arr2[0][0]) fmt.Printf("arr2[1][0]的地址%p ", &arr2[1][0]) } func a10(){ //直接初始化 var arr3 [2][3]int=[2][3]int{{1,2,3},{4,5,6}} fmt.Println(arr3) } //二位数组的遍历 func a11(){ var arr3=[2][3]int{{1,2,3},{4,5,6}} for i:=0;i<len(arr3);i++{ for j:=0;j<len(arr3[i]);j++{ fmt.Printf("%v ",arr3[i][j]) } fmt.Println() } //使用for-range遍历 for k,v:=range arr3{ for k2,v2:=range v{ fmt.Printf("arr3[%v][%v]=%v ",k,k2,v2) } fmt.Println() } } //应用案例 func a12(){ var scores [3][5]float64 for i:=0;i<len(scores);i++{ for j:=0;j<len(scores[i]);j++{ fmt.Printf("请输入第%d班第%d个学生的成绩 ",i+1,j+1) fmt.Scanln(&scores[i][j]) } } totalSum:=0.0 for i:=0;i<len(scores);i++{ sum:=0.0 for j:=0;j<len(scores[i]);j++{ sum+=scores[i][j] } totalSum+=sum fmt.Printf("第%d班级的总分为%v ",i+1,sum,sum/float64(len(scores[i]))) } fmt.Printf("所有班级的总分为%v,所有班级平均分为%v ", totalSum,totalSum/15) }
切片
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" //数组求和 func s1(x [3]int) { sum := 0 for _, v := range x { sum += v } fmt.Println(sum) } //声明切片类型 func s2() { // var a []string var b = []int{} var c = []bool{false, true} //var d = []bool{false, true} fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(a == nil) fmt.Println(b == nil) fmt.Println(c == nil) //fmt.Println(c==d) } //基于数组定义切片 func s3(){ a:=[5]int{55,56,57,58,59} b:=a[1:4] fmt.Println(b) fmt.Println(a[1:]) fmt.Println(a[:4]) fmt.Println(a[:]) fmt.Printf("%T ",b) }
测试
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" /* 1.切片是引用类型 2.切片是可动态变化的数组 */ //切片的基本使用 func q1() { var intArr [5]int = [...]int{1, 22, 33, 66, 99} slice := intArr[1:3] fmt.Println("intArr=", intArr) fmt.Println("slice的元素", slice) fmt.Println("slice长度", len(slice)) fmt.Println("slice容量", cap(slice)) fmt.Printf("slice的类型%T", slice) } //声明切片 func q2() { //方式一 var intArr [5]int = [...]int{1, 22, 33, 66, 99} fmt.Println(intArr) //方式二:使用make,由切片底层维护 var intArr2 []int = make([]int, 4, 10) fmt.Println(intArr2) //方式三 var strSlice []string = []string{"tom", "jack", "mary"} fmt.Println(strSlice) } //切片的遍历 func q3() { var arr [5]int = [...]int{10, 20, 30, 40, 50} slice := arr[1:4] for i := 0; i < len(slice); i++ { fmt.Printf("slice[%v]=%v", i, slice[i]) } fmt.Println() for i, v := range slice { fmt.Printf("i=%v v=%v ", i, v) } } //切片可以进行再次切片 //append动态追加 func q4() { var slice3 []int = []int{100, 200, 300} fmt.Println("slice3", slice3) //切片追加 slice3 = append(slice3, slice3...) fmt.Println("slice3", slice3) } //拷贝操作 func q5() { var slice4 []int = []int{1, 2, 3, 4, 5} var slice5 = make([]int, 10) copy(slice5, slice4) fmt.Println("clice4=", slice4) fmt.Println("slice5", slice5) } //切片实现斐波那契数列 func fbn(n int) []uint64 { fbnSlice := make([]uint64, n) fbnSlice[0] = 1 fbnSlice[1] = 1 for i := 2; i < n; i++ { fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2] } return fbnSlice } func main() { fbnSlice := fbn(20) fmt.Println("fbnSlice=", fbnSlice) }
删除切片
m1=append(m1[:1],m1[2:]...)
map
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" "sort" ) //初始化 func m1() { //方式一 var a map[string]string a = make(map[string]string, 10) a["n1"] = "宋江" a["n2"] = "吴用" a["n3"] = "武松" a["n4"] = "吴用" fmt.Println(a) //方式二 cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //方式三 heroes := map[string]string{ "hero1": "宋江", "hero2": "卢俊义", "hero3": "吴用", } heroes["hero4"] = "林冲" fmt.Println("hreoes=", heroes) } //二维map func m2() { studentMap := make(map[string]map[string]string) studentMap["stu01"] = make(map[string]string) studentMap["stu01"]["name"] = "tom" studentMap["stu01"]["sex"] = "男" studentMap["stu01"]["address"] = "长安街" studentMap["stu02"] = make(map[string]string) studentMap["stu02"]["name"] = "marry" studentMap["stu02"]["sex"] = "女" studentMap["stu02"]["address"] = "黄浦江" fmt.Println(studentMap) fmt.Println(studentMap["stu02"]) fmt.Println(studentMap["stu02"]["address"]) } //删除 func m3() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) delete(cities, "no2") fmt.Println(cities) } //判断元素是否存在 func m4() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" val, ok := cities["no2"] if ok { fmt.Printf("no2的值为%v", val) } else { fmt.Println("找不到") } } //map遍历 func m5() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" for k, v := range cities { fmt.Printf("k=%v v=%v ", k, v) } studentMap := make(map[string]map[string]string) studentMap["stu01"] = make(map[string]string, 3) studentMap["stu01"]["name"] = "tom" studentMap["stu01"]["sex"] = "男" studentMap["stu01"]["address"] = "长安街" studentMap["stu02"] = make(map[string]string, 3) studentMap["stu02"]["name"] = "marry" studentMap["stu02"]["sex"] = "女" studentMap["stu02"]["address"] = "黄浦江" for k1, v1 := range studentMap { fmt.Println("k1=", k1) for k2, v2 := range v1 { fmt.Printf(" k2=%v v2=%v ", k2, v2) } fmt.Println() } } //map切片 func m6() { var monsters []map[string]string monsters = make([]map[string]string, 2) if monsters[0] == nil { monsters[0] = make(map[string]string, 2) monsters[0]["name"] = "牛魔王" monsters[0]["age"] = "500" } if monsters[1] == nil { monsters[1] = make(map[string]string, 2) monsters[1]["name"] = "玉兔精" monsters[1]["age"] = "400" } newMOnstr := map[string]string{ "name": "火云邪神", "age": "200", } monsters = append(monsters, newMOnstr) fmt.Println(monsters) } //map排序 func m7() { map1 := make(map[int]int, 10) map1[10] = 100 map1[1] = 13 map1[4] = 56 map1[8] = 90 fmt.Println(map1) var keys []int for k, _ := range map1 { keys = append(keys, k) } sort.Ints(keys) fmt.Println(keys) for _, k := range keys { fmt.Printf("map1[%v]=%v ", k, map1[k]) } } //map是引用类型,修改值后会影响原来的 //会自动扩容 //结构体 //func m8(){ // students:=make(map[string]Stu,10) // stu1:=Stu{"tom",18,"北京"} // stu2:=Stu{"mary",17,"上海"} //students["no1"]=stu1 //students["no2"]=stu2 //fmt.Sprintln(students) //for k,v:=range students{ // //fmt.Printf("学生的编号%v,名字:%v,年龄:%v,地址:%v ",k,v.Name,v.Age,v.Address) //} //} //查找用户存在则修改,不存在则添加 func modifyUser(users map[string]map[string]string, name string) { //用户是否存在 if users[name] == nil { users[name]["pwd"] = "888888" } else { users[name] = make(map[string]string, 2) users[name]["pwd"] = "888888" users[name]["nickname"] = "昵称~" + name } } func main() { users := make(map[string]map[string]string, 10) users["smith"] = make(map[string]string, 2) users["smith"]["pwd"] = "999999" users["smith"]["nickname"] = "小花猫" modifyUser(users, "tom") modifyUser(users, "mary") modifyUser(users, "smith") fmt.Sprintln(users) }
删除map
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
重新make一个 m1=make(map[int]string) m1=nil
流程控制
顺序
循环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" "math/rand" "time" ) func f1() { j := 1 for j <= 10 { fmt.Println(j) j++ } } func f2() { k := 1 for { if k <= 10 { fmt.Println(k) } else { break } k++ } } func f3() { var str string = "hello world !" for i := 0; i < len(str); i++ { fmt.Printf("%c ", str[i]) } } func f4() { str := "abc~ok" for index, val := range str { fmt.Printf("index=%d val=%c ", index, val) } } //有中文时遍历 func f5() { str := "abc~ok上海" for index, val := range str { fmt.Printf("index=%d val=%c ", index, val) } } //使用切片遍历中文 func f6() { var str string = "hello world!北京" str2 := []rune(str) for i := 0; i < len(str2); i++ { fmt.Printf("%c ", str2[i]) } } //break 使用 func f7() { var count int = 0 for { rand.Seed(time.Now().UnixNano()) n := rand.Intn(100) + 1 fmt.Println("n=", n) count++ if n == 99 { break } } fmt.Printf("生成99一共使用了%d次", count) } //通过标签终止 func f8() { //label2: for i := 0; i < 4; i++ { //label1: for j := 0; j < 10; j++ { if j == 2 { break } fmt.Printf("%d-%d ", i, j) } } } //continue的使用 func f9() { for i := 0; i < 4; i++ { if i == 2 { continue } fmt.Println("i=", i) } } // func f10() { here: for i := 0; i < 2; i++ { for j := 0; j < 4; j++ { if j == 2 { continue here } fmt.Printf("i=%v j=%v ", i, j) } } } //打印菱形 /* ******** * * * * * * ******** */ func f11() { var height int = 30 //高 var width int = 30 //宽 for i := 1; i <= height; i++ { //打空格 for j := 1; j <= i-1; j++ { fmt.Print(" ") } //打星 for j := 1; j <= width; j++ { if (i == 1 || i == height) || (j == 1 || j == width) { fmt.Print("* ") } else { fmt.Print(" ") } } fmt.Println() } } func main() { f11() }
分支
循环
9*9乘法口诀
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//打印99乘法口诀 func formula() { for i := 1; i < 10; i++ { for j := 1; j < 10; j++ { if i <= j { fmt.Printf("%v*%v=%v ", i, j, i*j) } } fmt.Println(" ") } }
goto
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//goto 的使用 func main() { var n int = 30 fmt.Println("ok1") fmt.Println("ok2") if n > 20 { goto label } fmt.Println("ok3") fmt.Println("ok4") label: fmt.Println("ok5") }
函数
基础使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
func cal(n1 float64, n2 float64, operator byte) float64 { var res float64 switch operator { case '+': res = n1 + n2 case '-': res = n1 - n2 case '*': res = n1 * n2 case '/': res = n1 / n2 default: fmt.Println("输入错误") } return res } //求和与差,函数返回两个结果 func getSumAndSub(n1 int, n2 int) (int, int) { sum := n1 + n2 sub := n1 - n2 return sum, sub }
递归
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//递归函数,递减内容 func test(n int) { if n > 2 { n-- test(n) } fmt.Println("n=", n) //回归时输出2,2,3,回归与递进方向相反 } //改进版 func test2(n int) { if n > 2 { n-- test2(n) } else { fmt.Println("n=", n) } }
值传递
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//基本数据类型和数组默认都是值传递,即进行值拷贝,在函数内修改,不会影响原来的值。 func test02(n1 int) { n1 = n1 + 10 fmt.Println("test02 n1=", n1) } func main() { num := 20 /test02(num) fmt.Println("main() num=", num) }
函数作为数据类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
func getSum(n1 int, n2 int) int { return n1 + n2 } func myFun(funvar func(int, int) int, num1 int, num2 int) int { return funvar(num1, num2) } func main() { res2 := myFun(getSum, 50, 60) fmt.Println("res2=", res2) }
自定义数据类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//自定义数据类型 func f1() { //给int类型取别名,在go中会认为是两个数据类型 type myint int var num1 myint var num2 int num1 = 40 num2 = int(num1) //这里需要显示转换 fmt.Println("num1=", num1, "num2=", num2) fmt.Printf("num1类型%T,num2类型%T", num1, num2) } func getSum(num1 int, num2 int) int { return num1 + num2 } //定义一个函数为数据类型 type myFunType func(int, int) int func myFun2(funvar myFunType, num1 int, num2 int) int { return funvar(num1, num2) } func main() { res3 := myFun2(getSum, 500, 600) fmt.Println("res3=", res3) }
支持函数返回值命名
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//支持函数返回值命名 func getSumAndSub(n1 int, n2 int) (sum int, sub int) { sub = n1 - n2 sum = n1 + n2 return } func main() { a1, b1 := getSumAndSub(1, 2) fmt.Printf("a1=%v,b=%v", a1, b1) }
使用下划线忽略返回值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
func getSumAndSub(n1 int, n2 int) (sum int, sub int) { sub = n1 - n2 sum = n1 + n2 return } func main() { a1, _ := getSumAndSub(1, 2) fmt.Printf("a1=%v", a1) }
可变参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//可变参数 //求1到多个int类型数的和 func sum(n1 int, args ...int) int { sum := n1 for i := 0; i < len(args); i++ { sum += args[i] } return sum } func main() { res4 := sum(10, 23, 1) fmt.Printf("res4=%v", res4) }
匿名函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//全局匿名函数 var ( Fun1 = func(n1 int, n2 int) int { return n1 * n2 } ) //匿名函数 func f1() { res1 := func(n1 int, n2 int) int { return n1 + n2 }(10, 20) fmt.Println("res1=", res1) } //将匿名函数赋值给变量 func f2() { a := func(n1 int, n2 int) int { return n1 - n2 } res2 := a(10, 30) fmt.Println("res2=", res2) } func main() { //全局匿名函数使用 res4 := Fun1(4, 9) fmt.Println(res4) }
闭包函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" import "strings" //闭包函数 func AddUpper() func(int) int { //连续多次调用n的值被保存 var n int = 10 return func(x int) int { n = n + x return n } } // func AddUpper2() func(int) int { var n int = 10 var str = "hello" return func(x int) int { n = n + x str += string(36) fmt.Println("str=", str) return n } } //判断后缀名 func makeSuffix(suffix string) func(string) string { return func(name string) string { //如果没有指定后缀名就加上,否则直接返回 if !strings.HasSuffix(name, suffix) { return name + suffix } return name } } func main() { // f := AddUpper2() // fmt.Println(f(1)) // fmt.Println(f(2)) // fmt.Println(f(3)) //添加后缀名,两次传值实现 f2 := makeSuffix(".jpg") fmt.Println("文件名处理后=", f2("winter")) fmt.Println("文件名处理后=", f2("bird.jpg")) }
defer
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import "fmt" //defer的使用 func sum(n1 int, n2 int) int { //当go直行到defer,不会立即执行,先压入栈,函数执行完毕后,先入后出读取 defer fmt.Println("n1=", n1) defer fmt.Println("n2=", n2) res := n1 + n2 fmt.Println("res=", res) return res } //在defer将语句放入栈,也会将相关的值拷贝入栈 func sum1(n1 int, n2 int) int { //当go直行到defer,不会立即执行,先压入栈,函数执行完毕后,先入后出读取 defer fmt.Println("n1=", n1) defer fmt.Println("n2=", n2) n1++ n2++ res := n1 + n2 fmt.Println("res=", res) return res } //defer最佳实践 //defer的价值在于当函数执行完毕后,可以及时释放函数占用的资源 //1.最后关闭文件 //2.最后断开连接 func main() { res := sum1(10, 20) fmt.Println("res=", res) }
地址传值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//地址传值 func t1(n1 *int) { *n1 = *n1 + 10 } func main() { num := 20 t1(&num) fmt.Println("main(),num=", num) }
其他
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//未定义形参数据类型 func sum(n1, n2 float32) float32 { fmt.Printf("n1 type=%T ", n1) return n1 + n2 } //数据交换 func swap(n1 *int, n2 *int) { t := *n1 *n1 = *n2 *n2 = t } func main() { a := 10 b := 20 swap(&a, &b) //传入地址 fmt.Printf("a=%v,b=%v", a, b) }
系统函数
字符串操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" "strconv" "strings" ) //字符串的长度 func s1() { fmt.Println(len("4563")) } //字符串的遍历 func s2() { str2 := "hello北京" r := []rune(str2) for i := 0; i < len(r); i++ { fmt.Printf("字符串=%c ", r[i]) } } //字符串转整数 func s3() { n, err := strconv.Atoi("234") if err != nil { fmt.Println("转换错误:", err) } else { fmt.Println("转换成功:", n) } } //整数转字符串 func s4() { str := strconv.Itoa(12345) fmt.Printf("str=%v,类型=%T", str, str) } //字符串转[]byte func s5() { var bytes = []byte("hello go") fmt.Printf("bytes=%v ", bytes) } //[]byte转字符串 func s6() { str := string([]byte{97, 98, 99}) fmt.Printf("str=%v", str) } //十进制转2,8,16进制 func s7() { str := strconv.FormatInt(123, 2) fmt.Printf("123对应的二进制=%v ", str) str = strconv.FormatInt(123, 16) fmt.Printf("123对应的16进制=%v", str) } //查找子串是否在字符串中,存在返回true,否则返回false func s8() { b := strings.Contains("seafood", "ea") fmt.Printf("b=%v ", b) } //统计一个字符串中有几个指定的子串 func s9() { num := strings.Count("ceheese", "ee") fmt.Printf("num=%v ", num) } //字符串比较 func s10() { //不区分大小写 b := strings.EqualFold("abc", "Abc") fmt.Printf("b=%v ", b) //区分大小写 fmt.Println("结果:", "abc" == "Abc") } //返回子串出现的index值 func s11() { //返回子串第一次出现的index值 index := strings.Index("NLT_abcabcabc", "_") fmt.Printf("index=%v ", index) //返回子串最后一次出现的index值 index = strings.LastIndex("NLT_abcabcabc", "ab") fmt.Printf("last_index=%v ", index) } //字符串替换 func s12() { //-1,表示替换全部,n表示替换n个 str := "go go hello" str2 := strings.Replace(str, "go", "北京", -1) fmt.Printf("str=%v str2=%v ", str, str2) } //吧字符串分割成数组 func s13() { strArr := strings.Split("hello,world,ok", ",") for i := 0; i < len(strArr); i++ { fmt.Printf("str[%v]=%v ", i, strArr[i]) } fmt.Printf("strArr=%v ", strArr) } //将字符串字母大小写进行转换 func s14() { str := "goLang Hello" //全部转大写 fmt.Println(strings.ToUpper(str)) //全部转小写 fmt.Println(strings.ToLower(str)) } //去除字符串两侧空格,或其他字符 func s15() { fmt.Printf("str=%q ", strings.TrimSpace(" it is me ")) fmt.Printf("str=%q ", strings.Trim("! hello kitty !", "!")) //去除左侧字符 fmt.Printf("str=%q ", strings.TrimLeft("! hello kitty !", "!")) //去除右侧字符 fmt.Printf("str=%q ", strings.TrimRight("! hello kitty !", "!")) //匹配字符串开头 fmt.Printf("str=%v ", strings.HasPrefix("! hello kitty !", "!")) //匹配字符串结尾 fmt.Printf("str=%v ", strings.HasSuffix("! hello kitty !", "!")) }
时间和日期
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import ( "fmt" "time" ) func t1() { now := time.Now() fmt.Printf("now=%v now type=%T", now, now) //now=2020-01-02 14:15:50.2102829 +0800 CST m=+0.012982501 now type=time.Time } //获取其他日期信息 func t2() { now := time.Now() fmt.Printf("年=%v ", now.Year()) fmt.Printf("月=%v ", now.Month()) fmt.Printf("月=%v ", int(now.Month())) fmt.Printf("日=%v ", now.Day()) fmt.Printf("时=%v ", now.Hour()) fmt.Printf("分=%v ", now.Minute()) fmt.Printf("秒=%v ", now.Second()) } /* 年=2020 月=January 月=1 日=2 时=14 分=19 秒=57 */ //格式化日期 func t3() { now := time.Now() //方式一 fmt.Printf("当前年月日 %d-%d-%d %d:%d:%d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) dateStr := fmt.Sprintf("当前年月日 %d-%d-%d %d:%d:%d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) fmt.Printf("dateStr=%v ", dateStr) //方式二 格式化日期时间的第二种方式 fmt.Printf(now.Format("2006-01-02 15::04:05")) fmt.Println() fmt.Printf(now.Format("2006-01-02")) fmt.Println() fmt.Printf(now.Format("15:04:05")) } /* 时间常量 */ // const ( // Nanoseaond Duration = 1 //纳秒 // Microsecond = 1000 * Microsecond //微秒 // Millisecond = 1000 * Microsecond //毫秒 // Second = 1000 * Millisecond //秒 // Minute = 60 * Second //分钟 // Hour = 60 * Minute // ) //使用sleep() func t4() { i := 0 for { i++ fmt.Println(i) time.Sleep(time.Millisecond * 1000) if i == 100 { break } } } func t5() { //unix时间戳和UnixNano时间戳 now := time.Now() fmt.Printf("unix时间戳=%v unixnano=%v ", now.Unix(), now.UnixNano()) }
常用时间转换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
func t1() { now := time.Now() fmt.Println(now.Unix()) fmt.Println(now.Format("2006-01-02 15:04:05")) //格式化时间转为时间戳 loc, _ := time.LoadLocation("Local") //获取时区 tm2, _ := time.ParseInLocation("01/02/2006", "02/08/2015",loc) fmt.Println(tm2.Unix()) //1423353600 //时间戳转格式化时间 var ts int64 = 1423353600 tm := time.Unix(ts, 0) fmt.Println(tm.Format("2006-01-02 03:04:05")) }
异常处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "errors" "fmt" ) //异常处理 func e1() { //捕捉函数内异常 //报错后函数内终止,函数外继续执行 defer func() { err := recover() if err != nil { fmt.Println("err=", err) } }() num1 := 10 num2 := 0 res := num1 / num2 fmt.Println("res=", res) fmt.Print("123") } //错误处理 func e2() { //使用defer+recover来捕捉和处理异常 defer func() { err := recover() if err != nil { fmt.Println("err=", err) fmt.Println("发送邮件给管理员") } }() num1 := 10 num2 := 0 res := num1 / num2 fmt.Println("res=", res) fmt.Println("看不见我就对了") } //自定义错误 func readConf(name string) (err error) { if name == "config.ini" { return nil } else { //自定义错误 return errors.New("读取文件错误") } } func e3() { err := readConf("config2.ini") if err != nil { //输出错误并终止程序 panic(err) } fmt.Println("test02()继续执行。。。") } func main() { e3() fmt.Println("后面的代码") }
测试用例
执行所有测试
go test -v
执行指定文件
go test -v cal_test.go
执行指定函数
go test -v -test.run TestAddUpper
测试超时
执行指定函数
go test -v -test.run TestAddUpper -timeout 360m
cal.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main func addUpper(n int) int { res := 0 for i := 1; i <= n; i++ { res += i } return res } func getSub(n1 int,n2 int) int { return n1-n2 }
cal_test.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
最佳案例
monster.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package monster import ( "encoding/json" "fmt" "io/ioutil" ) type Monster struct { Name string Age int Skill string } //给Monster绑定方法Store,可以将一个MOnster变量(对象),序列化后保存到文件中 func (this *Monster) Store() bool{ //先序列化 data,err:=json.Marshal(this) if err!=nil{ fmt.Println("marshal err=",err) return false } //保存到文件 filePath:="d:/monster.ser" err=ioutil.WriteFile(filePath,data,0666) if err!=nil{ fmt.Println("write file err=",err) return false } return true } //给MOnster绑定方法ReStore ,可以将一个序列化的MOnster,从文件中读取 //并反序列化为MOnster对象,检查反序列化,名字正确 func (this *Monster) ReStore() bool{ //1.先从文件中,读取序列化的字符串 filePath:="d:/monster.ser" data,err:=ioutil.ReadFile(filePath) if err!=nil{ fmt.Println("ReadFile err=",err) return false } //2.使用读取到的data []byte,反序列化 err=json.Unmarshal(data,this) if err!=nil{ fmt.Println("unmarshal err=",err) return false } return true }
monster_test.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package monster import ( "testing" ) //测试用例,测试 Store 方法 func TestStore(t *testing.T) { //先创建一个Monster 实例 monster := &Monster{ Name : "红孩儿", Age :10, Skill : "吐火.", } res := monster.Store() if !res { t.Fatalf("monster.Store() 错误,希望为=%v 实际为=%v", true, res) } t.Logf("monster.Store() 测试成功!") } func TestReStore(t *testing.T) { //测试数据是很多,测试很多次,才确定函数,模块.. //先创建一个 Monster 实例 , 不需要指定字段的值 var monster = &Monster{} res := monster.ReStore() if !res { t.Fatalf("monster.ReStore() 错误,希望为=%v 实际为=%v", true, res) } //进一步判断 if monster.Name != "红孩儿" { t.Fatalf("monster.ReStore() 错误,希望为=%v 实际为=%v", "红孩儿", monster.Name) } t.Logf("monster.ReStore() 测试成功!") }
命令行输入(flag)
参数输入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" "os" ) func main() { fmt.Println("命令行的参数有",len(os.Args)) //遍历os.Args切片,就可以得到所有命令行参数 for i,v:=range os.Args{ fmt.Printf("args[%v]=%v ",i,v) } }
格式化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "flag" "fmt" ) func main() { var user string var pwd string var host string var port int flag.StringVar(&user, "u", "", "用户名,默认为空") flag.StringVar(&pwd, "pwd", "", "密码默认为空") flag.StringVar(&host, "h", "", "主机名,默认为localhost") flag.IntVar(&port, "port", 3306, "主机名,默认为localhost") //转换 flag.Parse() fmt.Printf("user=%v pwd=%v host=%v port=%v", user,pwd,host,port) }
参数输入
go 包引入
_ "go_code/test/hello/imp"
采用下划线引入只执行包的init方法,不能调用具体方法
main.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( _ "go_code/test/hello/imp" ) func main() { imp.Print() //编译报错,说:undefined: imp }
imp.go
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package imp import "fmt" func init() { fmt.Println("imp-init() come here.") } func Print() { fmt.Println("Hello!") }
正则匹配
注意:正则规则应该使用反引号,否则需要多加一层转义。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//匹配字节切片 判断 func r1() { flag, _ := regexp.Match("^\d{6,15}$", []byte("123456789")) fmt.Println(flag) flag, _ = regexp.Match("^\w{4,15}$", []byte("helo")) fmt.Println(flag) } //匹配字符串 func r2() { flag, _ := regexp.MatchString("^\d{4,9}", "123456") fmt.Println(flag) } //将正则表达式字符串编译成正则对象,可复用 func r3() { //Compile,MustCompile效果相同,compile错误返回err,MustCompile报panic MyRegexp, _ := regexp.Compile("^\d{6,7}\D{2}$") //MyRegexp2:=regexp.MustCompile("^\d{6,7}\D{2}$") //匹配字节数组 res := MyRegexp.Match([]byte("123456EE")) fmt.Println(res) //判断与字符串是否匹配 res2:=MyRegexp.MatchString("123456EE") fmt.Println(res2) } //对符合正则表达式的全部替换成指定内容 //字节数组匹配替换 func r4(){ t:="3[a]23[ac]7[p]" Myregexp:=regexp.MustCompile(`w+`) //字节切片匹配 res:=string(Myregexp.ReplaceAll([]byte(t),[]byte(" "))) fmt.Printf("%T,%v ",res,res) //字符串匹配 res=Myregexp.ReplaceAllString(t,"-") fmt.Printf("%T,%v",res,res) } //通过正则切割字符串 func r5(){ t:="第一部分#第二部分#第三部分#" //数字表示分成几个元素 MyRegexp:=regexp.MustCompile("#+") arr:=MyRegexp.Split(t,-1) fmt.Println(arr) }
匹配获取内容
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 把3[a]2[bc]ef转成 aaabcbcef */ func r2() { buf := "3[a]2[bc]ef" reg := regexp.MustCompile(`(d)[(w+)]`) reg_end := regexp.MustCompile(`w+$`) if reg == nil { fmt.Println("regexp err") return } res := reg.FindAllStringSubmatch(buf, -1) res_end := reg_end.FindAllStringSubmatch(buf, -1) fmt.Println(res_end[0][0]) fmt.Println("result=", res) var str string for _, v := range res { //fmt.Printf("%T,v=%v ",v[1],v[1]) var num int num, err := strconv.Atoi(v[1]) if err != nil { fmt.Println(err) } str += strings.Repeat(v[2], num) } if res_end != nil { str += res_end[0][0] } fmt.Println(str) }
随机数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//获取0-n随机数 func r1(){ //生成随机资源 s1:=rand.NewSource(time.Now().UnixNano()) fmt.Println(time.Now().Unix()) r1:=rand.New(s1) randnum:=r1.Intn(10) fmt.Println(randnum) } //获取0-10的随机数 func s2(){ rand.Seed(time.Now().UnixNano()) fmt.Println(rand.Intn(10)) //0-1随机数 fmt.Println(rand.Float64()) //获取m-n的随机数 //fmt.Println(rand.Intn(n-m+1)+m) m:=10 n:=12 fmt.Println(rand.Intn(n-m+1)+m) }
上下文context
context.WithCancel()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "context" "log" "os" "time" ) var ( logg *log.Logger ) func work(ctx context.Context, ch chan bool) { for { select { case <-ctx.Done(): logg.Println(`打豆豆!`) ch <- true return default: logg.Println(`睡觉!`) time.Sleep(2 * time.Second) } } } func main() { ch := make(chan bool) logg = log.New(os.Stdout, "", log.Ltime) ctx, cancel := context.WithCancel(context.Background()) go work(ctx, ch) time.Sleep(10 * time.Second) //取消函数:当cancel被调用时,WithCancel遍历Done以执行关闭; cancel() // 这个chan是为了保证子的goroutine执行完,当然也可以不用chan用time.Sleep停止几秒 <-ch logg.Println(`吃饭!`) }
context.WithDeadline()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "context" "log" "os" "time" ) var ( logg *log.Logger ) //返回Context和取消函数用来取消Context(这个取消函数会根据设置的时间自动取消) func work(ctx context.Context, ch chan bool) { for { select { case <-ctx.Done(): logg.Println(`打豆豆!`) ch <- true return default: logg.Println(`睡觉!`) time.Sleep(2 * time.Second) } } } func main() { ch := make(chan bool) logg = log.New(os.Stdout, "", log.Ltime) ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second)) go work(ctx, ch) time.Sleep(10 * time.Second) //取消函数:当cancel被调用时,context.WithDeadline设置的时间超过了,关闭ctx.Done通道。 cancel() // 这个chan是为了保证子的goroutine执行完,当然也可以不用chan用time.Sleep停止几秒 <-ch logg.Println(`吃饭!`) }
context.WithTimeout()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "context" "log" "os" "time" ) var ( logg *log.Logger ) func work(ctx context.Context, ch chan bool) { for { select { case <-ctx.Done(): logg.Println(`打豆豆!`) ch <- true return default: logg.Println(`吃饭!`) time.Sleep(2 * time.Second) } } } //context.WithCancel():执行取消函数就取消 //context.WithDeadline、context.WithTimeout:超时的时候就取消 func main() { ch := make(chan bool) logg = log.New(os.Stdout, "", log.Ltime) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) go work(ctx, ch) time.Sleep(10 * time.Second) //取消函数:当cancel被调用时,context.WithTimeout设置的时间超过后,关闭ctx.Done通道; cancel() // 这个chan是为了保证子的goroutine执行完,当然也可以不用chan用time.Sleep停止几秒 <-ch logg.Println(`睡觉!`) }
Deadline
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "context" "fmt" "log" "os" "time" ) var ( logg *log.Logger ) func work(ctx context.Context, ch chan bool) { for { /* Deadline:是获取设置的超时时间: 第一个返回值:设置的超时时间,到超时时间Context会自动发起取消请求 第二个返回值ok==false时表示没有设置截止时间,如果需要取消的话需要调用取消函数进行取消。 */ if deadline, ok := ctx.Deadline(); ok { fmt.Println(deadline) if time.Now().After(deadline) { logg.Println(`超时退出!`) //这里是为了演示,Context中的Err()输出:context deadline exceeded logg.Printf(ctx.Err().Error()) ch <- true return } } select { case <-ctx.Done(): logg.Println(`下班!`) ch <- true return default: logg.Println(`上班!`) time.Sleep(1 * time.Second) } } } func main() { ch := make(chan bool) logg = log.New(os.Stdout, "", log.Ltime) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) go work(ctx, ch) time.Sleep(10 * time.Second) //取消函数:当cancel被调用时,context.WithTimeout设置的时间超过后,关闭ctx.Done通道; cancel() // 这个chan是为了保证子的goroutine执行完,当然也可以不用chan用time.Sleep停止几秒 <-ch logg.Println(`无脑发呆中!`) }
context.WithValue
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "context" "fmt" ) func main() { ProcessRequest("jane", "abc123") } type ctxKey int const ( ctxUserName ctxKey = iota ctxPassWord ) //上下文数据存取 func UserName(c context.Context) string { return c.Value(ctxUserName).(string) } func PassWord(c context.Context) string { return c.Value(ctxPassWord).(string) } func ProcessRequest(UserName, PassWord string) { ctx := context.WithValue(context.Background(), ctxUserName, UserName) ctx = context.WithValue(ctx, ctxPassWord, PassWord) HandleResponse(ctx) } func HandleResponse(ctx context.Context) { fmt.Printf( "处理响应 用户名:%v 密码:%v", UserName(ctx), PassWord(ctx), ) } /* outfile: 处理响应 用户名:jane 密码:abc123 */
。。。。