目录
switch
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough 。
package main
import "fmt"
func main() {
var a=6666
switch a {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
case 3:
fmt.Println("3")
case 666:
fmt.Println("666")
default:
fmt.Println("上面条件都不符合时,执行我。")
}
}
// case后跟多个条件,用逗号隔开。
func main() {
var a=667
switch a {
case 1,2,3:
fmt.Println("1")
case 4,5,6:
fmt.Println("2")
case 7,8,9:
fmt.Println("3")
case 666,667:
fmt.Println("666")
default:
fmt.Println("上面条件都不符合时,执行我。")
}
}
package main
import "fmt"
func main() {
var a=667
switch {
case a==1:
fmt.Println("1")
case a == 2 && a == 3: // &&类似Python中的and
fmt.Println("2")
case a == 666 || a == 667: // ||类似Python中的or
fmt.Println("我是666,要么667")
default:
fmt.Println("上面条件都不符合时,执行我。")
}
}
// fallthrough case语句中有fallthrough,会无条件执行紧跟着的下一个case语句
package main
import "fmt"
func main() {
var a=8
switch {
case a==8:
fmt.Println("8")
fallthrough
case a==9 && a==10: // &&类似Python中的and
fmt.Println("9,10")
fallthrough
case a == 11: // ||类似Python中的or
fmt.Println("11")
}
}
数组
数组:数组是同一类元素的集合,类似于Python中的列表(列表可以放任意元素)
Python中列表放任意元素是因为一切皆对象,对象是一个引用(内存地址)。
数组的声明
var a [数组长度] 数组类型
package main
import "fmt"
func main(){
// 定义一个长度为3的int类型数组
var a [3] int
// 定义一个长度为3的string类型数组
var b [3] string
// 定义一个长度为3的bool类型数组
var c [3] bool
fmt.Println(a) // int 类型空值为0
fmt.Println(b) // string 类型空值为""
fmt.Println(c) // bool 类型空值为false
}
定义并初始化
//var a [3]int =[3]int{1,2,3}
//var a=[3]int{1,2,3}
a:=[3]int{1,2,3} // 定义的数组的长度一旦固定,后期就没法扩容
fmt.Println(a[2])
fmt.Println(a[2]) // 取数组索引为2的值
修改数组某个/些位置上的值
var a[10]int=[10]int{8:9,9:10}
// 将数组的第8个位置改为9,第9个位置改为10
fmt.Println(a)
fmt.Println(a[10]) // 取值的时候不能超长,会报错
// 打印结果:[0 0 0 0 0 0 0 0 9 10]
数组是值类型
// 数组是值类型(值类型,引用类型),当做函数传参,传到函数内部,修改数组,不会影响原来的; go中函数传参,都是copy传递
python中可变类型和不可变类型(一切皆对象,都是引用)python强行把 数字,字符串,元组做成不可变数据类型.
1.数字,字符串,元组做成不可变数据类型,当做参数传参,在函数中修改不可变数据类型,不会改变原来的
2. 其他的,在函数中修改,都会影响原来的
// python是值传递还是引用传递?
Python参数传递统一使用的是引用传递方式。因为Python对象分为可变对象(list,dict,set等)和不可变对象(number,string,tuple等),当传递的参数是可变对象的引用时,因为可变对象的值可以修改,因此可以通过修改参数值而修改原对象
当传递的参数是不可变对象的引用时,虽然传递的是引用,参数变量和原变量都指向同一内存地址,但是不可变对象无法修改,所以参数的重新赋值不会影响原对象。
package main
import "fmt"
func main() {
var a[3]int=[3]int{1,2,3}
fmt.Println(a)
test(a)
fmt.Println(a)
}
func test(x [3]int) {
x[0] = 999
fmt.Println(x)
}
/*
[1 2 3]
[999 2 3]
[1 2 3]
*/
数组的长度
var a[3]int=[3]int{1,2,3}
fmt.Println(len(a))
循环数组
// 使用range迭代数组
//第一种方式
var a =[3]int{2,4,6}
for i:=0;i<len(a);i++{
fmt.Println(a[i])
}
/*第二种通过range, range不是一个内置函数,它是一个关键字
i:=range a i是索引 ,一个值来接收,就是索引
i,v:=range a i是索引,v是具体的值,如果两个值来接收,就是索引和值
*/
var a =[3]int{2,4,6}
for i,v:=range a{
fmt.Println(i,v)
}
/*
打印结果:
0 2
1 4
2 6
*/
如果想忽略掉索引,可以用"_","_"和Python中的"_"不一样,Python中"_"是一个变量,而go中"_"不是变量。
多维数组(数组套数组)
var a [3][3]int
fmt.Println(a)
/*
[[0 0 0] [0 0 0] [0 0 0 ]]
*/
// 定义并初始化
var a [3][3]int=[3][3]int{{1,2,3},{4,5,6},{7,8}}
// 使用
a[0][1]=999
fmt.Println(a)
/*
[[1 999 3] [4 5 6] [7 8 0]]
*/
数组的大小是类型的一部分
package main
import "fmt"
func main(){
var a[3]int
var b[4]int
test(b) // 数组b的大小与test形参定义的大小不匹配 报错
}
func test(a[3]int){
int.Println(a)
}
package main
import "fmt"
func main(){
var a[3]int
var b[3]int
a=b // 数组大小相等,才能赋值
fmt.Println(a)
}
切片(slice)
创建一个切片
/*
切片:切片是由数组建立的一种方便、灵活且功能强大的包装,
切片本身不拥有任何数据。它们只是对现有数组的引用.
*/
package main
import "fmt"
func main (){
//1 创建一个切片
//先创建一个 数组
var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
//创建切片(基于上面的数组切出来,从第0个位置切到最后一个位置)
var b =a[:]
var c =a[5:] //第5个位置切到最后
var d =a[5:9] //第5个位置切到第9个位置,前闭后开区间
//中括号有东西,就是数组,没有东西就是切片
var e[]int =a[5:9]
fmt.Println(b,c,d,e)
}
切片的修改
//2 切片的修改(切片的修改会影响原来的数组,数组的修改也会影响切片)
var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
var b[]int =a[5:9]
//切片修改影响数组
b[0]=999
//数组修改,影响切片
a[6]=888
fmt.Println(a)
fmt.Println(b)
切片的长度和容量
//3 切片的长度和容量
//len() :长度,现在有多少值
//cap() :容量,总共能放多少值
var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
var b[]int =a[5:9]
//var b[]int =a[0:3]
//var b[]int =a[2:3]
fmt.Println(len(b))
// 底层基于数组,它的容量就是当前指针位置往后到末尾数组的长度,这部分切片都可以放值。
fmt.Println(cap(b))
/*
4
5
*/
使用make创建一个切片
//切片空值是?nil类型(引用类型空值都是nil)
var a []int
fmt.Println(a)
if a==nil{
fmt.Println("我是空的")
}
a[0]=100 //这样报错,因为我们定义的切片a的长度为0,
//make内置函数。第一个参数写类型,第二个参数是切片的长度,第三个参数是切片的容量
var a []int=make([]int,3,4) // 切片底层基于数组,这里使用make创建切片,其底层是make先创建一个数组,然后再根据这个数组创建切片。
//var a []int=make([]int,3) //长度是多少3,容量是3,容量如果不传,默认跟长度一样
a[0]=999
//a[9]=100 // 改值超出了长度,报错
a[2]=999 //中括号取,只能取到长度
////a[3]=888 //报错!!!! 容量是4,所以是还可以放一个值的,是追加的方式,不是这样赋值。
fmt.Println(a)
fmt.Println(len(a))
fmt.Println(cap(a))
/*
[999 0 999]
3
4
*/
追加切片元素
var a[]int=make([]int,3,4)
// 在最后追加一个元素999
a=append(a,999)
fmt.Println(a)
fmt.Println(len(a))
fmt.Println(cap(a))
/*
[0 0 0 999]
4
4
*/
a=append(a,888) //切片a的长度已经达到容量了,再追加会怎么样?不会报错,
//追加的时候,一旦超过容量,会重写创建一个数组,让切片指向新的数组,新数组大小是原来切片容量的两倍
a=append(a,888)
a=append(a,888)
a=append(a,888)
fmt.Println(a)
fmt.Println(len(a))
fmt.Println(cap(a))
/*
[0 0 0 999 888 888 888 888]
8
8
*/
//切片如果基于数组切出来
var a [10]int=[10]int{1,2,3,4,5,6,7,8,9,10}
var b[]int =a[5:9]
b=append(b,777)
fmt.Println(a)
fmt.Println(b)
b=append(b,666) //这里追加值,已经超容,容量变成原来的两倍。现在就不会依赖原来的数组了,现在再改变,不会影响原来的数组了
fmt.Println(a)
fmt.Println(b)
fmt.Println(len(b))
fmt.Println(cap(b))
b[0]=11111
fmt.Println(a)
fmt.Println(b)
/*
[1 2 3 4 5 6 7 8 9 777]
[6 7 8 9 777]
[1 2 3 4 5 6 7 8 9 777]
[6 7 8 9 777 666]
6
10
[1 2 3 4 5 6 7 8 9 777]
[11111 7 8 9 777 666]
*/
切片的函数传递
package main
import "fmt"
func main (){
//6 切片的函数传递(引用类型,传递,修改原来的)
var a []int=make([]int,4,5)
fmt.Println(a)
test2(a) //copy传递
fmt.Println(a)
}
func test2(b []int) {
b[0]=999
b=append(b,888)
fmt.Println(b)
fmt.Println(cap(b))
}
/*
[0 0 0 0]
[999 0 0 0 888]
5
[999 0 0 0]
*/
多维切片
var a [][]int=make([][]int,3,4)
if (a[0]==nil){
fmt.Println("多维切片的空值nil")
}
fmt.Println(a)
/*
多维切片的空值nil
[[] [] []]
*/
//7 多维切片
// 一维切片初始化
var a []int=[]int{1,2,3,4,5} //类似于数组初始化,切片初始化
fmt.Println(a)
fmt.Println(len(a))
fmt.Println(cap(a))
/*
[1 2 3 4 5]
5
5
*/
// 多维切片初始化
var a [][]int=[][]int{{1,2,3},{2,3},{4,5,5,6,7,8,9}}
fmt.Println(a)
fmt.Println(len(a[2]))
fmt.Println(cap(a[2]))
a[0][1]=999
fmt.Println(a)
/*
[[1 2 3] [2 3] [4 5 5 6 7 8 9]]
7
7
[[1 999 3] [2 3] [4 5 5 6 7 8 9]]
*/
切片copy
//8 切片copy
var a []int=make([]int,4,5)
var b []int =[]int{1,2,3,4,5}
fmt.Println(a)
fmt.Println(b)
//把b的数据copy到a上
copy(a,b)
fmt.Println(a) // a的长度只有4,从b上copy也只能是4个
fmt.Println(b)
/*
[0 0 0 0]
[1 2 3 4 5]
[1 2 3 4]
[1 2 3 4 5]
*/
var a []int=make([]int,6,7)
var b []int =[]int{1,2,3,4,5}
fmt.Println(a)
fmt.Println(b)
//把b的数据copy到a上
copy(a,b)
fmt.Println(a) // a的长度是6,b的长度只有5,从b上copy,数目不够补0。
fmt.Println(b)
/*
[0 0 0 0 0 0]
[1 2 3 4 5]
[1 2 3 4 5 0]
[1 2 3 4 5]
*/
map
map是在Go中将值[value]与键[key]关联的内置类型,通过相应的键可以获取值。
创建map
// 通过向make函数传入键和值的类型,可以创建map。
// 创建map语法:
var map[key的类型]value的类型
// 定义并初始化(使用make)
var map[key的类型]value的类型=make([key的类型]value的类型)
package main
import "fmt"
func main(){
// 定义一个map
// map的空值是什么? nil (引用类型的空值都是nil)
var a map[int]string // 定义一个map,如果没有初始化,是空值,nil类型
fmt.Println(a)
if a==nil{
fmt.Println("我是空的")
}
}
/*
map[]
我是空的
*/
package main
import "fmt"
func main(){
// 定义并初始化
var a map[int]string=make(map[int]string)
//也可以如下简略写法
//var a =make(map[int]string)
//a :=make(map[int]string)
fmt.Println(a)
fmt.Println(a==nil) // a已经初始化了,a就不再是nil类型了。
// 定义并初始化,直接赋值。
var b map[int]string = map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
}
/*
map[]
false
map[1:zhang 2:wang 3:li 4:zhao]
*/
给map添加元素
// map中没有这个元素,就添加;有这个元素就更新
// var a map[int]string
// a[1]="zhang" // 因为定义的一个map还没有初始化,就相当于往nil里面添加元素,会报错。
a :=make(map[int]string)
a[1]="zhang"
// a[2]=123 // 在定义阶段类型就已经定了,这里不能再使用其他类型的value。
// a[1]="wang" // 像Python中的字典,更新key对应的value。
fmt.Println(a)
/*
map[1:zhang]
*/
获取map中的元素
package main
import "fmt"
func main(){
var b map[int]string = map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
fmt.Println(b[1])
fmt.Println(b[5]) // 取不到,会打印出value值的默认值(空值);如果值的类型是int,取map中不存在的key,则打印的是0
}
package main
import "fmt"
func main(){
var a map[int]string = map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
//从字典中取值,其实会返回两个值,一个是true和false,一个是真正的值
//如果用一个变量来接,就是值(可能为空,可以能有值),两个变量接,一个是值,一个是true和false
b,ok1:=a[9] // 取不存在的key
c,ok2:=a[1] // 取存在的key
fmt.Println(b,ok1)
fmt.Println(c,ok2)
}
/*
false
zhang true
*/
删除map中的元素
var a map[int]string= map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
fmt.Println(a)
//根据key删除值
delete(a,1)
fmt.Println(a)
/*
map[1:zhang 2:wang 3:li 4:zhao]
map[2:wang 3:li 4:zhao]
*/
获取map的长度
package main
import "fmt"
func main(){
var a map[int]string= map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
a[9]="999"
fmt.Println(len(a))
}
// 4
map是引用类型
package main
import "fmt"
func main(){
var a map[int]string= map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
fmt.Println(a)
test(a)
fmt.Println(a)
}
test(a map[int]string){
a[1]="xx"
fmt.Println(a)
}
/*
map[1:zhang 2:wang 3:li 4:zhao]
map[1:xx 2:wang 3:li 4:zhao]
map[1:xx 2:wang 3:li 4:zhao]
*/
map的相等性
package main
import "fmt"
func main(){
var a map[int]string= map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
//var b map[int]string= map[int]string{1:"zhang",2:"wang",3:"li",4:"zhao"}
//if a==b() // //map是引用类型,不能通过等号来判断,这样对比的是地址;自己写循环,一个个取判断
for k,v:=range a{ // go当中的map是无序的
fmt.Println(k,v)
}
}
/*
2 wang
1 zhang
4 zhao
3 li
*/
map的value值可以是任意类型
var a map[int]map[string]string=make(map[int]map[string]string) // map的value类型还是一个map
//fmt.Println(a==nil) // false
//fmt.Println(a[1]==nil) // true
// 报错了
a[1]=make(map[string]string)
a[1]= map[string]string{"1":"zhang"}
a[1]["1"]="zhang"
fmt.Println(a)
// map[1:map[1:zhang]]
将map中的字典(无序)做成有序
package main
import (
"fmt"
"sort"
)
func main(){
slice1 :=map[string]int{
"zhang":12,
"wang":15,
"li":14,
"zhao":11,
"sun":16,
}
var names []string
for name :=range slice1 {
names = append(names,name)
}
sort.Strings(names)
for _,name :=range names{
fmt.Printf("%s %d
",name,slice1[name])
}
}
/*
[zhang wang li zhao sun]
[li sun wang zhang zhao]
li 14
sun 16
wang 15
zhang 12
zhao 11
*/