数组
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"
}