切片
1.什么是切片
切片本身不拥有任何数据,它们只是对现有数组的引用。
2.切片的定义
1.方式1:由数组切出来:var 变量名 []元素类型 = 数组名[开始值:结束值] //1.定义数组 var a [8]int=[8]int{1,2,3,4,5,6,7,8} //2.定义切片,注意[]中没有数字 var b []int=a[2:6] fmt.Println(b) // [3 4 5 6] //更多用法,没有步长 var a [8]int=[8]int{1,2,3,4,5,6,7,8} b:=a[:4] fmt.Println(b) //[1 2 3 4] 2.方式2:直接定义不赋值。 注意:切片空值是?nil类型 var a []int fmt.Println(a) //[],注意:切片空值是?nil类型 if a==nil{ fmt.Println("我是空的") } //a[0]=10 //报错 fmt.Println(a) 方式3:make(类型,切片长度,切片容量) var a []int=make([]int,3,4) fmt.Println(a) //[0 0 0] //切片的长度和容量(len cap:容量) var a [8]int=[8]int{1,2,3,4,5,6,7,8} var b []int=a[2:6] fmt.Println(len(b)) //4 fmt.Println(cap(b)) //6 var a []int=make([]int,3,4) fmt.Println(a) fmt.Println(len(a)) //3 fmt.Println(cap(a)) //4 3.切片的常用操作 1.切片的长度和容量(len:长度,cap:容量) //var a [8]int=[8]int{1,2,3,4,5,6,7,8} //var b []int=a[2:6] //fmt.Println(len(b)) //4 //fmt.Println(cap(b)) //6 var a []int=make([]int,3,4) fmt.Println(a) fmt.Println(len(a)) //3 fmt.Println(cap(a)) //4 2.切片追加值:append(切片名,值1,值2) var a [8]int=[8]int{1,2,3,4,5,6,7,8} var b []int=a[2:6] b = append(b, 9,10) fmt.Println(b) //[3 4 5 6 9 10] fmt.Println(a) //[1 2 3 4 5 6 9 10],数组的值也被修改为增加的值 //当容量到顶,在添加值时 b = append(b, 11) fmt.Println(b) //[3 4 5 6 9 10 11] fmt.Println(len(b)) //7 fmt.Println(cap(b)) //12,容量翻倍 fmt.Println(a) //[1 2 3 4 5 6 9 10]容量到顶在添加值数组值不在改变 3.修改值:切片名[索引] = 修改值 var b =make([]int,3,4) b[0]=999 fmt.Println(b) //[999 0 0] //超过容量,在修改值时 var a [6]int=[6]int{1,2,3,4,5,6} var b []int=a[1:6] fmt.Println(a) //[1 2 3 4 5 6] fmt.Println(b) //[2 3 4 5 6] b= append(b, 7) a[0] = 2 b[0] = 1 fmt.Println(a) //[2 2 3 4 5 6] fmt.Println(b) //[1 3 4 5 6 7] 总结:追加和修改没超过容量时,一个变另一个跟着变。超过时数组和切片没有关系。 4.切片的函数传递 var b =make([]int,3,4) test(b) fmt.Println(b) func test(b []int) { b[0]=999 fmt.Println(b) } 5.切片的数据结构表示 var a [][]string=make([][]string,2,3) fmt.Println(a) //[[] []] fmt.Println(a[0]) //[] 6.多维切片 var a [][]string=make([][]string,2,3) fmt.Println(a) //[[] []] fmt.Println(a[0]) //[] a[0]=make([]string,2,3) //嵌套内的切片在初始化 if a[0]==nil{ fmt.Println("xxxx") } 7.多维切片初始化 var a [][]string=[][]string{{"1","2"},{"3","4"}} fmt.Println(a) //[[1 2] [3 4]] fmt.Println(len(a)) //2 fmt.Println(cap(a)) //2 a[0][1]="999" fmt.Println(a) //[[1 999] [3 4]] 8.copy函数:copy(源,目标) var a =make([]int,3,10000) a[1]=99 a[2]=888 fmt.Println(a) //[0 99 888] var b =make([]int,2,4) fmt.Println(b) //[0 0] copy(b,a) fmt.Println(b) //[0 99]
3.打散和循环
1.打散
var a =[]int{1,2,4,} test1(1,2,3,4) test1(a...) //变量名...:相当于打散了 veggies := []string{"potatoes", "tomatoes", "brinjal"} fruits := []string{"oranges", "apples"} food := append(veggies, fruits...) fmt.Println("food:",food) func test1(a ...int) { fmt.Println(a) fmt.Printf("%T",a) }
2.循环
//循环多维切片
pls := [][]string {
{"C", "C++"},
{"JavaScript"},
{"Go", "Rust"},
}
fmt.Println(pls)
for _,v:=range pls {
for _,v1:=range v{
fmt.Println(v1)
}
}
map
1.什么是map
类似于python中的字典,map 是在 Go 中将值(value)与键(key)关联的内置类型。通过相应的键可以获取到值。
2.map的定义和常用方法
1.方式1:var 变量名 map[键值类型]value值类型 var a map[int]string fmt.Println(a) //map[]map的空值是nil类型 //执行下列if语句 if a==nil{ fmt.Println("xxxx") } 2. map的初始化 var a map[int]string=make(map[int]string) fmt.Println(a) //map[]此时不是nil类型注意区分 //不执行下列语句 if a==nil{ fmt.Println("xxxxx") } 3.赋值:变量名[k] = v,取值:变量名[k],取一个不存在的key值会?返回value值类型的空值 var a map[int]string=make(map[int]string) fmt.Println(a) //map[] if a==nil{ fmt.Println("xxxxx") } // 赋值 a[1]="100" a[2]="888" fmt.Println(a) //map[1:100 2:888] //取值 fmt.Println(a[1]) //100 取值补充: 值,ok:=变量名[k] =>k存在ok为ture,反之为false if v,ok:=a[9];ok{ fmt.Println("=-====",v) }else { fmt.Println("该值不存在") } 4.方式2:定义和初始化 var a =map[int]string{1:"10",2:"100"} fmt.Println(a[1]) 5.字典删除元素,内置函数:delete(变量名,k) var a =map[int]string{1:"10",2:"100"} delete(a,2) fmt.Println(a) 6.长度:len(变量名) var a =map[int]string{1:"10",2:"100"} fmt.Println(len(a)) 7.map循环 var a =map[int]string{1:"10",0:"100",10:"999"} //map是无序的 for k,v:=range a{ fmt.Println(k) fmt.Println(v) } 8.map的相等性:map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil,判断两个 map 是否相等的方法是遍历比较两个 map 中的每个元素。我建议你写一段这样的程序实现这个功能 map1 := map[string]int{ "one": 1, "two": 2, } map2 := map1 if map1 == map2 { //报错 }
字符串
1.什么是字符串
Go 语言中的字符串是一个字节切片。把内容放在双引号""之间,我们可以创建一个字符串。让我们来看一个创建并打印字符串
2.字符串常用方式
1.统计字节数:len(变量名)。统计字符串长度;utf8.RuneCountInString(变量名) 在go种string类型都是utf-8编码 name := "Hello World刘清政" fmt.Println(len(name)) //20 fmt.Println(utf8.RuneCountInString(name)) //14 2.字符串循环 方式1:按字节循环 name := "name刘" for i:=0;i<len(name);i++{ fmt.Println(string(name[i])) fmt.Printf("%T",name[i]) fmt.Println() } 方式2:按字符循环 name := "name刘" for _,v:=range name{ fmt.Println(string(v)) fmt.Printf("%T",v) fmt.Println() }
指针
1.什么是指针
指针:是一种存储变量内存地址(Memory Address)的变量。
2.指针的类型,地址,反解
1.指针变量的类型为: *值类型(地址关联值的)
示例 b := 255 var a *int = &b //应为地址对应的值为255即int类型
2.获取地址:&变量名
示例:获取a的地址
a:=10
b:=&a
3.反解(根据地址获取值):*地址变量名
3.指针的定义和其他使用
1.方式1 a:=10 b:=&a 2.方式2 d:="sss" var c *string=&d 3.方式3嵌套 a:=10 var b *int =&a var c **int=&b 4.指针的零值(Zero Value),nil类型 a := 25 var b *int //初始化 if b == nil { fmt.Println("b is", b) b = &a //赋值 fmt.Println("b after initialization is", b) 运行结果: b is <nil> b after initialisation is 0x1040a124 5.向函数传递指针参数 a:=10 b:=&a test6(b) fmt.Println(a) //11 func test6(b *int) { //*b 就是 a a++ *b++ fmt.Println(*b) //11 6.不要向函数传递数组的指针,而应该使用切片 //不建议使用 //var a [100]int //test9(&a) //fmt.Println(a) //推荐使用 test10(a[:]) func test9(a *[100]int) { (*a)[0]=999 fmt.Println(a) } func test10(a []int) { a[0]=999 fmt.Println(a) fmt.Println(a) }
结构体
1.什么是结构体
一系列属性的结合体(类似于python中的类)
2.结构体类型和零值
1.结构体和结构体对象的类型就是:结构变量名
2.是结构体属性默认类型的默认值
3.结构体的定义
语法:
type关键字 结构体名字 struct{
属性名1 类型
属性名2 类型
}
方式1:示例
type Person struct {
name string
sex ,age int
}
4.结构体实例化与使用
1.定义结构体 type Person struct { name string sex ,age int } 2.实例化:结构体名{} #1. #实例不初始化 person :=Person{} //{ 0 0}默认值为各个属性的默认值 #实例不初始化:var 实例化名 结构体类型 var person Person fmt.Println(person) //{ 0 0}默认值为各个属性的默认值 #2.实例化并赋初始值 方式1:关键字赋值,有的属性可以不传值 var person Person=Person{name:"lqz",sex:1,age:19} fmt.Println(p)//{lqz,1,19} 方式2:位置赋值,必须全部赋值 var person Person=Person{"lqz",1,19} fmt.Println(p)//{lqz,1,19} 3.
取值:
实例化名.属性名
改值:
实例化名.属性名 = 新的值
5.匿名结构体
1.指的的是没有名字的结构体 变量定义 = struct { 属性1 类型 属性2 类型 }{属性1:值,属性2:值} 2.示例 a:=struct { name string age int }{"lqz",19} fmt.Printf(a.name)
6.结构体指针
4.结构体指针 结构体和结构体指针都可以通过点语法查看值 p:=Person{name:"lqz"} var pPoint *Person=&p //fmt.Println(pPoint) //fmt.Println((*pPoint).name) //lqz fmt.Println(pPoint.name) //lqz
7.匿名字段
4.匿名字段(用作变量提升) type Person struct { string int } //p:=Person{"lqz",19} //位置实例化 p:=Person{string:"lqz",int:19} //关键字实例化,关键字为类型名 fmt.Println(p.string)
8.嵌套结构体和变量提升
1.嵌套结构体 //定义被嵌套结构体 type Person struct { name string sex ,age int hobby Hobby //嵌套结构体 } //定义嵌套结构体 type Hobby struct { id int name string } 实例化使用 p:=Person{name:"lqz",hobby:Hobby{10,"篮球"}} //p:=Person{name:"lqz",hobby:Hobby{id:10,name:"篮球"}} p.hobby.id=101 2.结构体嵌套+匿名字段 type Person struct { name string sex ,age int Hobby } type Hobby struct { id int //hobbyname string name string } p:=Person{name:"lqz",Hobby:Hobby{10,"篮球"}} //取p中的hobbyname两种方式,变量提升过程中如果有重名的,就不提升了 fmt.Println(p.Hobby.hobbyname) //fmt.Println(p.hobbyname)