Go 数据类型
数组
package main import ( "fmt" ) //数组:数组是同一类型元素的集合。可以放多个值,但是类型一致,内存中连续存储 // Go 语言中不允许混合不同类型的元素 func main() { //1 数组的定义,数组的大小,在定义阶段就确定了,而且不能改 //定义了一个大小为3的string类型数组,里面可以放3个字符串 //var names [3]string //var ages [3]int8 //fmt.Println(ages) //2 数组赋值 //var ages [3]int8 //ages[0]=99 //ages[2]=88 //fmt.Println(ages) //fmt.Println(ages[1]) //3 定义并初始化, //var ages [3]int=[3]int{1,2,3} //var ages [3]int=[3]int{1,2} //var ages [3]int=[3]int{} //var ages=[3]int{} //ages:=[3]int{1,3,4,7} //不允许多放 //fmt.Println(ages) //4 数组定义并初始化的其他(了解)数组只要定义,长度就固定了,。。。,后面放几个值,数组大小是多少 //var ages [9]int=[...]int{1,2,3,4,5,6,7,8} //不支持这个 //var ages =[...]int{1,2,3,4,5,6,7,8} //ages :=[...]int{1,2,3,4,8} //fmt.Println(len(ages)) //5 数组的大小是类型的一部分 //var a [2]int=[2]int{1,2} //var b [2]int=[2]int{1,3} //b=a //如果不是同一种类型,不允许相互赋值 //fmt.Println(b) //6 数组是值类型 //var a [2]int=[2]int{1,2} //fmt.Println(a) //test5(a) //因为数组是值类型,go函数传参,都是copy传递,如果是值类型,函数内改了,不会影响原来的 //fmt.Println(a) //7 数组长度 len() 数组长度在定义阶段已经固定 //var a [2]int=[2]int{1,2} //fmt.Println(len(a)) //8 数组循环 //var a =[...]int{7,4,3,5,6,7} //fmt.Println(a[99]) //fmt.Println(len(a)) //普通循环 //for i:=0;i<len(a);i++{ // fmt.Println(a[i]) //} //通过range来循环 (range不是内置函数,是一个关键字,for,if,else),打印出索引 //for i:=range a{ // fmt.Println(i) //} //如果用一个变量来接收,这个值是可迭代的索引 //如果用两个变量来接收,这两个变量,一个是索引,一个具体的值 //for i,value:=range a{ // fmt.Println(i) // fmt.Println(value) //} //把数组循环打印出来 //for _,value:=range a{ // fmt.Println(value) //} // 9 多维数组 //var a [3][3]int //定义 //a[0][1]=99 //使用 //fmt.Println(a) //定义并赋初值 //var a [3][3]int=[3][3]int{{1},{1,2,3},{4,4,4}} //var s =[3][3]string{{"lqz","xxx","yyy"},{},{}} //fmt.Println(s) // ////循环多维数组 //for _,value:=range s{ // for _,in_value:=range value{ // fmt.Println(in_value) // } //} //10 数组定义并指定位置初始化 //var names [100]int=[100]int{10:99,99:99} //var names [100]int=[100]int{10,11,2,44,99:99,45:88} //fmt.Println(names) } func test5(a [2]int) { a[0]=99 fmt.Println(a) }
切片
package main import "fmt" //切片:可以变长, //切片是对底层数组的引用 //切片的改变会影响底层数组 //底层数组的改变,会影响切片 //切片的追加可能会触发扩容,一旦扩容,就不再依赖于原来的底层数组了 func main() { //var a []int //var b [3]int //fmt.Printf("%T",a) //fmt.Println() //fmt.Printf("%T",b) //切片的初始化,从数组切出来 //var a [10]int //b是切片 //b:=a[:] //var b []int=a[:] //从开头切到结尾,赋值给切片b //fmt.Println(b) //fmt.Printf("%T",b) //切片的修改 //b[0]=99 //a[0]=888 //fmt.Println("b-----",b) //fmt.Println("a-----",a) //切片的长度和容量 //var a [10]int ////var b []int=a[3:] //var b []int=a[3:6] ////a[3]=999 //b[2]=222 ////fmt.Println(a) //fmt.Println(b) //fmt.Println(len(b)) //3 //fmt.Println(cap(b)) //7 //b[3]=999 //不可以 index out of range [3] with length 3 //var c []int=a[8:] //fmt.Println(len(c)) //3 //fmt.Println(cap(c)) //切片定义的第二种方式,通过make创建 //创建了一个长度为2,容量为4的切片 //var a []int=make([]int,2,4) //等同于 //b:=[4]int{0,0,0,0} //a:=b[0:2] //fmt.Println(len(a)) //fmt.Println(cap(a)) //创建了一个长度为2,容量为2的切片 //var a []int=make([]int,2) //fmt.Println(len(a)) //fmt.Println(cap(a)) //扩容,追加切片 //var a []int=make([]int,2,4) //a[0]=111 //a[1]=222 //fmt.Println(a) ////使用内置函数append //a=append(a,333,444) //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //临界点到了 //a=append(a,555) //fmt.Println(a) //111 222 333 444 555 //fmt.Println(len(a)) //5 //fmt.Println(cap(a)) //8,自动扩容,在原来容量的基础上扩一倍 ////切片超过了最大容量,底层数组重新创建,重新指向新的数组 //a=append(a,666,777,888,999) //fmt.Println(a) // //fmt.Println(len(a)) //9 //fmt.Println(cap(a)) //16 //切片超过了最大容量,底层数组重新创建,重新指向新的数组 //var a [10]int //b:=a[8:] //fmt.Println(b) //fmt.Println(len(b)) //fmt.Println(cap(b)) //a[9]=999 //fmt.Println(a) //fmt.Println(b) //b[0]=888 //b=append(b,666) //fmt.Println("aaaa",a) // //fmt.Println("------") //fmt.Println(b) //fmt.Println(len(b)) //fmt.Println(cap(b)) ////改掉数组的最后一个值 //a[9]=1234 //fmt.Println(b) //b[0]=666 //fmt.Println("----------------") //fmt.Println(b) //fmt.Println(a) //切片的函数传递,切片是引用类型,引用类型的空值是nil //所有引用类型的空置都是nil //var a[]int=[]int{1,2,3} ////长度是3,容量是3 //fmt.Println(len(a)) //fmt.Println(cap(a)) ////fmt.Println(a) // //if a==nil{ // fmt.Println("空的") //}else { // fmt.Println("不是空") //} //var a[]int=[]int{1,2,3} //test(a) //fmt.Println(a) // 999 2 3 影响原来的 //多维切片 //var a [][]string=[][]string{{"lqz","egon"},{"zs"},{}} //第一层的切片:长度是3 ,容量是3 //第二层的切片:不确定,根据初始化的情况判断 //fmt.Println(len(a[2])) //fmt.Println(cap(a[2])) //var a [][]string=make([][]string,3,4) //fmt.Println(a) //if a[2]==nil{ // fmt.Println("空") //} //a[2]=make([]string,3,4) //fmt.Println(a[2][0]) //copy 内置函数 //var a [10000]int //b:=a[:2] //b[0]=111 //b[1]=222 // //var c []int=make([]int,1,4) ////把b copy到c身上 //copy(c,b) //fmt.Println(c) var c []int=[]int{3,4,5,6,7,8,9,9} //for i:=0;i<len(c);i++{ // fmt.Println(c[i]) //} for _,v:=range c{ fmt.Println(v) } } func test(a []int) { a[0]=999 fmt.Println(a)// 999 2 3 a=append(a,777) //如果扩容了,以后再改的,不会影响原来的,如果没扩容,修改会影响原来的 fmt.Println(a) // 999 2 3 777 a[0]=444 fmt.Println(a)// 444 2 3 777 }
字符串
package main //字符串 import ( "fmt" ) //len字符串看到的是字节长度 func printBytes(s string) { for i:= 0; i < len(s); i++ { //fmt.Printf("%x ", s[i]) fmt.Println(s[i]) } } func main() { //name := "Hello World" //name := "中国" ////printBytes(name) //runeLen(name) } func runeLen(s string) { //字符长度 //res:=utf8.RuneCountInString(s) //fmt.Println(res) //for i:=0;i<utf8.RuneCountInString(s);i++{ // fmt.Println((s[i])) //} }
maps
package main import "fmt" //maps 字典,存储key value的的数据结构 func main() { //1 定义 //int是key值类型,string是value类型 //引用类型,空值是nil //var m map[int]string //if m==nil{ // fmt.Println("空") //} //定义并初始化 //var m map[int]string= map[int]string{1:"lqz",2:"egon"} //var m = map[int]string{1:"lqz",2:"egon"} m:=map[int]string{199:"lqz",200:"egon"} fmt.Println(m) //添加元素 m[1]="zhangsan" fmt.Println(m) //获取元素 //fmt.Println(m[199]) //获取的元素不在map中,结果取决于value值的类型 //fmt.Println(m[2]) //m1:=map[int]int{1:1} //fmt.Println(m1[2]) //判断元素是否再map中 //m1:=map[int]int{1:111} ////value是key对应的值,如果不存在,为value的空值 ////flag 是个bool值,如果不存在,是false,如果存在是true //value,flag:=m1[1] //fmt.Println(value) //fmt.Println(flag) // 循环map (python字典有序?3.6以后有序了) /* python字典的底层结构:https://www.cnblogs.com/xiaoyuanqujing/articles/12008689.html 在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面。 但是从Python 3.6开始,字典是变成有顺序的了。你先插入键值对A,后插入键值对B,那么当你打印Keys列表的时候,你就会发现B在A的后面 [key,key,key] */ //go语言的map是无序的 //m1:=map[int]int{1:111,4:444,8:888} //m1[5]=999 //m1[3]=888 //for k,v:=range m1{ // fmt.Println("k是",k,"v是",v) //} //删除元素 //m1:=map[int]int{1:111,4:444,8:888} //delete(m1,4) //fmt.Println(m1) //map的长度 //fmt.Println(len(m1)) //fmt.Println(cap(m1)) //使用make初始化map,数字不用填,这个数字其实是底层数组的大小 //m2:=make(map[int]int) //m2[1]=11 //m2[2]=222 //m2[3]=333 //m2[4]=444 //m2[5]=555 //fmt.Println(m2) //map 是引用类型 //m2:=make(map[int]int) //m2[1]=11 //m2[2]=222 //m2[3]=333 //m2[4]=444 // //test6(m2) //fmt.Println(m2) //map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil //m2:=make(map[int]int) //m2[1]=11 // //m3:=make(map[int]int) //m3[1]=11 // ////两个map之间不允许直接比较 //if m2==nil{ // //} } func test6(m map[int]int) { m[1]=999 }
指针
package main import "fmt" //指针:变量,存内存地址 //指针是一种存储变量内存地址的变量。 //取地址符号 & ,写在一个变量前,表示取该变量的地址 //* 放在类型前,表示该类型的指针 //* 放在变量前,表示解引用(取该地址对应的值) func main() { //var a int=10 ////指针类型的变量 ////b:= &a //var b *int=&a ////fmt.Println(b) // ////c:=&b //var c **int=&b // //var d ***int=&c //fmt.Println(d) // //fmt.Println(***d) //指针的0值:<nil>,引用类型 //var a *int //fmt.Println(a) //指针的解引用 //s:="lqz" ////s_p:=&s //var s_p *string=&s //fmt.Println(*s_p) //向函数传递指针参数 //var a =10 //test2(&a) //fmt.Println(a) //s:="lqz" //test3(&s) //fmt.Println(s) //不要向函数传递数组的指针,而应该使用切片 //var a=[4]int{6,8,9} //6,8,9,0 //test4(&a) //取了数组的地址,传入了test4 //fmt.Println("-----",a) // //test5(a[:]) //fmt.Println("-----",a) //指针不支持运算(c语言指针支持运算) //var a =[3]int{9,7,6} //b:=&a ////b++ //不支持 //fmt.Println(b) // 指针数组和数组指针 var a *[3]int //指向数组的指针 指向这种数组的指针[3]int a=&[3]int{1,2,43} fmt.Println(a) var b [3]*int //大小为3,内部放int类型的指针 a1,a2,a3:=10,20,30 b[0]=&a1 b[1]=&a2 b[2]=&a3 fmt.Println(b) } func test4(a *[4]int) { //(*a)[0]=999 //解引用,改值 a[0]=999 //等同于上面,数组的指针不需要解引用再通过索引取值,直接通过索引取值即可 fmt.Println(a) } func test5(a []int) { a[0]=999 fmt.Println(a) } func test2(a *int) { fmt.Println(a)//地址 fmt.Println(*a) //解引用 10 *a=100 } func test3(a *string) { fmt.Println(*a) *a="ssssss" }