package main import ( "container/list" "fmt" "math" "sort" "strings" "sync" ) const ( Unknown = 0 Female = 1 Male = 2 ) func main() { var ( a int b string ) c := 10 d := 20 //交换变量值 d, c = c, d fmt.Println(d) fmt.Println(c) fmt.Println(a) fmt.Println(b) fmt.Println("hello world") e, _ := getData() _, f := getData() fmt.Println(e) fmt.Println(f) //g1 := true //使用反引号`定义多行字符串: var temp string temp = ` x := 10 y := 20 z := 30 fmt.Println(x, " ", y, " ", z) x, y, z = y, z, x fmt.Println(x, " ", y, " ", z) ` fmt.Println(temp) //Go语言数据类型转换 //浮点型与整型之间的转换 chinese := 90 english := 80.9 avg := (chinese + int(english)) / 2 avg2 := (float64(chinese) + english) / 2 fmt.Printf("%T, %d ", avg, avg) fmt.Printf("%T, %f ", avg2, avg2) //:在Go语言中,不允许字符串转 int,否则会产生如下错误。 //常量 fmt.Println(Unknown, Female, Male) var aa bool = true var ba bool = false if aa && ba { fmt.Printf("第一行 - 条件为 true ") } if aa || ba { fmt.Printf("第二行 - 条件为 true ") } num := 20 if num%2 == 0 { fmt.Println(num, "是偶数") } else { fmt.Println(num, "是奇数") } //在定义时调用匿名函数 func(data int) { fmt.Println("hello", data) }(100) // 将匿名函数赋值给变量 ff := func(datas string) { fmt.Println(datas) } ff("将匿名函数赋值给变量") //匿名函数用作回调函数 // 调用函数,对每个元素进行求平方根操作 arr := []float64{1, 9, 16, 25, 30} // 调用函数,对每个元素进行求平方根操作 visit(arr, func(v float64) { v = math.Pow(v, 2) fmt.Printf("%.0f ", v) }) var nums = [...]int{1, 2, 3, 4, 5} fmt.Printf("数组 a 的长度为 %d,数组 b 的长度为 %d ", len(nums), len(nums)) //遍历数组方式1 for i := 0; i < len(nums); i++ { fmt.Print(nums[i], " ") } fmt.Println() //遍历数组方式2 for _, value := range nums { fmt.Print(value, " ") } //三行 每行4个值得二维数组 erweiarr := [3][4]int{ {0, 1, 2, 3}, /* 第一行索引为0 */ {4, 5, 6, 7}, /* 第二行索引为1 */ {8, 9, 10, 11}, /* 第三行索引为2 */ } fmt.Println(erweiarr) //声明切片 /*创建切片*/ numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} fmt.Printf("len=%d cap=%d slice=%v ", len(numbers), cap(numbers), numbers) /*打印子切片从索引1(包含)到索引4(不包含)*/ fmt.Println("numbers[1:4] ==", numbers[1:4]) /*默认下限为0*/ fmt.Println("numbers[:3] ==", numbers[:3]) /*默认上限为len(s)*/ fmt.Println("numbers[4:] ==", numbers[4:]) /*打印子切片从索引0(包含)到索引2(不包含)*/ number2 := numbers[:2] fmt.Println("number2 ==", number2) /*打印子切片从索引2(包含)到索引5(不包含)*/ number3 := numbers[2:5] fmt.Println("number3 ==", number3) //定义数组 arrr := [3]int{1, 2, 3} //根据数组截取切片 nums1 := arrr[:] //数组转为切片 nums2 := arrr[:] fmt.Println("arrr=", arrr) nums1[0] = 100 fmt.Println("arrr=", arrr) nums2[1] = 200 fmt.Println("arrr=", arrr) //Go语言len()和cap():获取切片长度和容量 //切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。切片可以通过 len() 方法获取长度,可以通过 cap() 方法获取容量。数组计算 cap() 结果与 len() 相同,具体使用细节如下所示。 arr0 := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"} fmt.Println("cap(arr0)=", cap(arr0), arr0) //截取数组, 形成切片 s01 := arr0[2:8] fmt.Printf("%T ", s01) fmt.Println("cap(s01)=", cap(s01), s01) s02 := arr0[4:7] fmt.Println("cap(s02)=", cap(s02), s02) //截取切片, 形成切片 s03 := s01[3:9] fmt.Println("截取s01[3:9]后形成s03:", s03) s04 := s02[4:7] fmt.Println("截取s02[4:7]后形成s04:", s04) //切片是引用类型 s04[0] = "x" fmt.Print(arr0, s01, s02, s03, s04) numberse := make([]int, 0, 20) numberse = append(numberse, 0) fmt.Println("numberse= ", numberse) /*同时添加多个元素*/ numberse = append(numberse, 2, 3, 4, 5, 6, 7) fmt.Println("numberse= ", numberse) //追加一个切片 s1 := []int{100, 200, 300, 400, 500, 600, 700} numberse = append(numberse, s1...) fmt.Println("numberse= ", numberse) //删除第一个元素 numberse = numberse[1:] fmt.Println("numberse= ", numberse) //删除最后一个元素 numberse = numberse[:len(numberse)-1] fmt.Println("删除最后一个元素= ", numberse) var country = map[string]string{ "China": "关联数组", "Japan": "Tokyo", "India": "New Delhi", "France": "Paris", "Italy": "Rome", } fmt.Println(country) for k, v := range country { fmt.Println("国家", k, "首都", v) } //查看元素在集合中是否存在 //可以通过 key 获取 map 中对应的 value 值。语法为:map[key]。 // 当 key 不存在时,会得到该 value 值类型的默认值, // 比如 string 类型得到空字符串,int 类型得到 0,程序不会报错。 // 所以可以通过value, ok := map[key]获知 key/value 是否存在。ok 是 bool 型,如果 ok 是 true,则该键值对存在,否则不存在。 value, ok := country["England"] if ok { fmt.Println("首都:", value) } else { fmt.Println("首都信息未检索到!") } //或者 if value, ok := country["Japan"]; ok { fmt.Println("首都 :", value) } else { fmt.Println("首都信息未检索到!") } //2. 根据key删除map中的某个元素 if _, ok := country["Italy"]; ok { delete(country, "Italy") } fmt.Println(country) //判断是否包含子串 fmt.Println(strings.Contains("seafood", "foo")) //将字符串 s 每个单词首字母大写返回 fmt.Println(strings.Title("her royal highness")) //将字符串 s 转换成大写返回 fmt.Println(strings.ToTitle("louD noises")) //按字典顺序比较a和b字符串大小 fmt.Println(strings.Compare("abc", "bcd")) fmt.Println("abs" < "bcd") //判断s和t两个UTF-8字符串是否相等, 忽略大小写 fmt.Println(strings.EqualFold("Go", "go")) //将字符串s重复count次返回 fmt.Println("g" + strings.Repeat("o", 8) + "le") //将a中的所有字符连接成一个字符串, 使用字符串sep作为分隔符 s := []string{"abc", "ABC", "123"} fmt.Println(strings.Join(s, ", ")) fmt.Println(strings.Join(s, ";")) ss := "hel" + "lo," ss += "world!" fmt.Println(ss) //输出 “hello, world!” // 创建一个整型切片,并赋值 slice := []int{10, 20, 30, 40} // 迭代每一个元素,并显示其值 for index, value := range slice { fmt.Printf("Index: %d Value: %d ", index, value) } // 声明一个二维整型切片并赋值 erslice := [][]int{{10}, {100, 200}} fmt.Println("声明一个二维整型切片并赋值", erslice) // 为第一个切片追加值为 20 的元素 erslice[0] = append(erslice[0], 30) fmt.Println("为第一个切片追加值为 30 的元素", erslice) erslice[1] = append(erslice[1], 50) fmt.Println("为第二个切片追加值为 50 的元素", erslice) //访问map中的每一个键值对 scene := make(map[string]int) scene["route"] = 66 scene["brazil"] = 4 scene["china"] = 960 for k, v := range scene { fmt.Println(k, v) } // 声明一个切片保存map数据 var sceneList []string // 将map数据遍历复制到切片中 for k := range scene { sceneList = append(sceneList, k) } // 对切片进行排序 sort.Strings(sceneList) // 输出 fmt.Println(sceneList) //在并发环境中使用的map //Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。 /*sync.Map 有以下特性: 无须初始化,直接声明即可。 sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。*/ var scenebf sync.Map // 将键值对保存到sync.Map scenebf.Store("greece", 97) scenebf.Store("london", 100) scenebf.Store("egypt", 200) // 从sync.Map中根据键取值 fmt.Println(scenebf.Load("london")) // 根据键删除对应的键值对 scenebf.Delete("london") // 遍历所有sync.Map中的键值对 scenebf.Range(func(k, v interface{}) bool { fmt.Println("iterate:", k, v) return true }) //list(列表) /*初始化列表 list 的初始化有两种方法:分别是使用 New() 函数和 var 关键字声明,两种方法的初始化效果都是一致的。 1) 通过 container/list 包的 New() 函数初始化 list 变量名 := list.New() 2) 通过 var 关键字声明初始化 list var 变量名 list.List 给 list 添加元素:*/ //双链表支持从队列前方或后方插入元素,分别对应的方法是 PushFront 和 PushBack l := list.New() l.PushBack("fist") l.PushFront(67) // 尾部添加 l.PushBack("canon") // 头部添加 l.PushFront(67) // 尾部添加后保存元素句柄 element := l.PushBack("fist") // 在fist之后添加high l.InsertAfter("high", element) // 在fist之前添加noon l.InsertBefore("noon", element) // 使用 l.Remove(element) //遍历列表——访问列表的每一个元素 //遍历双链表需要配合 Front() 函数获取头元素,遍历时只要元素不为空就可以继续进行,每一次遍历都会调用元素的 Next() 函数,代码如下所示。 for i := l.Front(); i != nil; i = i.Next() { fmt.Println("list:", i.Value) } //使用结构体类 //顺序初始化,每个结构体中定义的成员必须都初始化 var s11 Student = Student{1, "mike", 'm', 18, "bj"} fmt.Println("s1 = ", s11) //指定某个成员初始化,没有指定的成员默认自动赋值为0 s22 := Student{name: "小明", addr: "bbb"} fmt.Println(s22) //使用里面的成员 //定义一个结构体类普通变量 var s12 Student // 操作成员,需要使用点 < .>运算符,就跟使用java中的 response类中的参数一样 s12.id = 1 s12.addr = "北京" s12.age = 28 s12.name = "望京soho" s12.sex = 'm' fmt.Println("结构体类使用s12:", s12) //定义一个指针变量,用来保存s12的地址 var p1 *Student p1 = &s12 //取地址s12 //通过指针操作成员,p1.id 和 (*p1).id 完全等价,只能使用 . 运算符 p1.id = 1 (*p1).name = "aisi" p1.sex = 'm' p1.age = 18 p1.addr = "soho" fmt.Println("p1=", p1) //通过new来实例化结构体类 p2 := new(Student) p2.id = 1 p2.name = "aisi" p2.sex = 'm' p2.age = 18 p2.addr = "soho" fmt.Println("p2=", p2) //结构体使用函数传参 s13 := Student{1, "mike", 'm', 18, "bj"} test01(s13) fmt.Println("s13:", s13) //计算价格函数调用 jiagezong := jisuan(10, 2) fmt.Println("zongjia :", jiagezong) //Go 语言支持一个函数可以有多个返回值。我们来写个以矩形的长和宽为输入参数,计算并返回矩形面积和周长的函数rectProps。 // 矩形的面积是长度和宽度的乘积, 周长是长度和宽度之和的两倍。即: area, perimeter := rectProps(10.8, 10.2)//如果不知道 := 前面返回类型,可以转中后面,ctrl alt +v 自己生成 fmt.Printf("Area= %f Perimeter= %f", area, perimeter) /*空白符 _ 在 Go 中被用作空白符,可以用作表示任何类型的任何值。我们继续以 rectProps 函数为例,该函数计算的是面积和周长。假使我们只需要计算面积, 而并不关心周长的计算结果,该怎么调用这个函数呢?这时,空白符 _ 就上场了。*/ area1, _ := rectProps(10.8, 10.2)//如果不知道 := 前面返回类型,可以转中后面,ctrl alt +v 自己生成 fmt.Printf("Area1111= %f", area1) //Golang当中只有一种循环,就是for循环。没有while,更没有do while循环 for i := 0; i < 10; i++ { fmt.Println(i) } //简写 for i :=0; ;i++ { fmt.Println("简写方式:",i) if i>10{ break } } } //写一个计算价格的函数,输入参数是单件商品的价格和商品的个数,两者的乘积为商品总价,作为函数的输出值。 /*func 函数名(参数名 参数类型) returntype { // 函数体(具体实现的功能) }*/ func jisuan(price int, num int) int { var totalPrice = price * num // 商品总价 = 商品单价 * 数量 return totalPrice // 返回总价; 返回值类型跟上面的返回值类型统一,就跟java的类差不多意思 } //Go 语言支持一个函数可以有多个返回值 func rectProps(length, width float64) (float64, float64) { var area = length * width var perimeter = (length + width) * 2 return area, perimeter } //方式er 有多个返回值 /*func rectProps(length, width float64)(area, perimeter float64) { area = length * width perimeter = (length + width) * 2 return // 不需要明确指定返回值,默认返回 area, perimeter 的值 }*/ //结构体,相当于PHP的类,在main中使用 type Student struct { id int name string sex byte age int addr string } func test01(s Student) { s.id = 666 fmt.Println("test01:", s) } func getData() (int, int) { return 100, 200 } // 定义一个函数,遍历切片元素,对每个元素进行处理 func visit(list []float64, f func(float64)) { for _, value := range list { f(value) } }