大家好,我是练习时长两天半的个人练习生。
变量定义
var name type
var name type = 值
var name = 值(自动判断类型
name := 值(全局变量定义的时候不可以这样
常量定义:
const name type = 值
变量类型:
变量类型包括但不限于,int,float,string,bool等类型
go的输入输出
需要提前导入包
import "fmt"
输出:
fmt.Print()打印
//如:fmt.Print(变量,变量,"字符串",变量……)
fmt.Printf()格式化打印
//如:fmt.Printf("……%d……",变量)
//这个需要用到占位符
//%T是一种占位符,用于输出对应变量的类型
//%v 默认格式输出值
//这俩比较常用,此外还有%d,%f……
fmt.Println()打印之后换行
//如:fmt.Println(变量,变量,变量……)
输入:
fmt.scan(&变量,&变量……)
fmt.scanln(&name)//读取一行数据,按照空格分隔
fmt.scanf("%d %s",&name,&name2)//格式化输入
运算符:+*/%,功能和C语言一样
逻辑运算符:
&& || !
true && true = true
true && false = true
false &&false =false
true || true = true
true || false = true
false || fasle = false
!true = false
!false = true
if语句
if 表达式1 {
语句块1(买个包
}else if 表达式2{
语句块2(买两个包
}else{
语句块3(买三个包
}
假设表达式1是你,表达式2是你对象。那如果你是对的,就给你对象买个包,如果你不是对的就看你对象是不是对的,如果你对象是对的就给你对象买俩包。否则就买三个包
逻辑:判断表达式1的bool值,true执行函数体1,false跳过,判断表达式2,true执行函数体2,如果都不满足则执行表达式3
if后面可以跟一个语句加分号然后才是判断的条件,如果初始化语句定义了一个变量,那这个变量作用域为整个if语句包括这个if的else
if 初始化语句;条件{
}
switch
switch name{
csae one:
a1
case two:
a2
case three:
a3
default:
a4
}
根据name去匹配one,two,three。值一样执行对应语句,执行完一个case或者default之后会自动结束switch语句
name,one,two,three这四个变量的类型需要一致,one!=two!=three不能重复
default,可有可无,作为switch的兜底。case的都不符合就会执行这个
同样,switch后面也可以跟一个语句加分号之后才是需要判断的条件
switch自带break,就是每个case结束之后会自动break,当然也可以自己在语句中加上break~
那这时候我们又会想念c里面的switch,可以执行多个case的内容。这时候就需要借助fallthrough
num:=2
switch num{
case 1:
fmt.Print("nihao")
case 2:
fmt.Print("hello")
fallthrough
case 3:
fmt.Print("word")
在这个情况下case23都会被执行,原因就是我们在case2所对应的语句部分加了一个fallthrough
switch num:=10;num{
……
}
//num作用域仅限于switch语句内
one,two,three可以是变量与name去比对,也可以是逻辑表达式,如果逻辑表达式为true就执行对应语句,如果是逻辑表达式,那么switch之后就不需要跟变量了
switch {
case 逻辑表达式1:
a1
case 逻辑表达式2:
a2
}
如果one和two的对应功能是一样的,那么就可以这样写:
switch num{
case 1,2,3:
fmt.Println("小于等于3")
}
for语句:
for 表达式1;表达式2;表达式3{
函数体
}
逻辑:先运行表达式1,然后执行表达式2。一般来说表达式1都是对循环变量的赋值与定义,表达式2是循环条件,条件满足执行函数体,然后再执行表达式3,表达式3执行完再执行表达式2,知道表达式2不满足,循环结束
也可以只有一个表达式2
for 表达式2{
函数体
}
类似于while
甚至三个都省略
for {
函数体
}
类似于for(;;)
这时候就会有疑问:表达式2作为循环条件被省略,那不成了一个死循环吗??
这时候就需要念出神奇咒语呼唤break
var num int = 10
for {
num++
if num > 20 {
fmt.Print("tuichu")
break
}
}
break就可以直接跳出当前所在的循环啦
那如果我们想单独略过某一次循环呢?
这时候就需要借助continue了捏
var num int = 10
for {
num++//更新循环变量
if num == 15 {//条件满足执行continue
fmt.Print("continue\n")
continue
}
fmt.Println(num)//输出当前循环变量的值
if num > 20 {//如果大于20了就退出循环
fmt.Print("tuichu\n")
break
}
}
运行结果如下
11
12
13
14
continue
16
17
18
19
20
21
tuichu
goto
goto语句是无条件跳转
num := 10
loop:
fmt.Println("yeyeyeyeye")
for ; num <= 15; num++ {
if num == 13 {
num++
goto loop
}
}
}
在上面的代码里,我们只要是num == 13就会执行自增和goto
获取时间戳:
t1 := time.Now()// 获取当前时间
//它获取的是一个time对象
//然后我们可以使用:
time1 := ti.Unix()
//这个是返回从1970.1.1 0.0.0到现在所经过的秒数
time2 := t1.UnixNano()
//这个是返回从1970.1.1 0.0.0到现在所经过的纳秒数
//time1和time2都是int64类型
诶~
那我们获取这个时间戳有个毛用
如果哪天我们突然想创建一个随机数的时候就需要用到这个时间戳了
随机数
//生成随机数需要这几个步骤
//1.
rand.Seed(time.Now().UnixNano())
//设置一个种子,因为种子是不断变化的,所以我们每次运行程序的时候种子都是新种子
//2.
rand.Intn(100)//生成[0,99]的随机数
数组
//新建数组
var name [size] type
//定义并初始化
var name = [size]type{……}
//...自动推断数组
var name = [...]type{……}
//还可以:
num := [size] type{}//一般来说,这个用的次数较多
//创建一个长度是size的数组(下标是0到size-1),数组内存储type类型的元素
//访问第?个元素
name[?]// ?
数组的值传递
//如果我们需要两个相同的数组的时候我们可以直接让一个数组等于另一个数组
arr1 :={1,2,3,4,5,6,7,8,9}
arr2:=arr1
//此时arr2里面存储的值就是和arr1相等
//而且,arr2是一个独立的,就是说改变arr1或者arr2都不会影响到另一个存储的元素
//这里顺嘴提一下值类型和引用类型
值类型包括 int,float,string,bool,array
这种类型存储的是数值本身,如果将数据传递给其他变量,传递的是数据的值
引用类型,除了值类型都是引用类型呗
这种类型存储的是数据的内存地址
数组遍历~
//定义数组
numbers := [10]{}
//遍历数组
for num:=0;num下标
//t->对应值
//循环完数组之后会自动停止循环
}
数组排序
一般来说go语言没有内置的排序函数,需要把数组类型转化为别的类型,然后才可以快捷排序
but!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我们有排序算法:如经典的冒泡排序,选择排序
go 冒泡排序
go 选择排序
这个是我个人对冒泡排序的理解,可以看一下
多维数组
//二维数组
//定义:
arr :=[3][3] int{{1,2,3},{4,5,6},{7,8,9}}
//这样就简单的定义了一个二维数组。二维数组的遍历需要使用嵌套循环
for i:=0;i<3;i++{
for j:=0;j<3;j++{
fmt.Print(arr[i][j],"\t")
}
fmt.Println()
}
//给二维数组赋值
for i:=0;i<3;i++{
for j:=0;j<3;j++{
fmt.Scanf("%d",&arr[i][j])
}
fmt.Println()
}
切片
存储一组类型相同的数据,和数组相比他可以变长(是引用类型
定义
var name []type//不需要说明长度
//切片
//1.通过数组创建切片
arr1 := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} //长度=容量
//定义一个数组
fmt.Println("通过数组创建切片")
slice := arr1[2:5] //创建一个slice切片,他的值引用的是数组的2-5下标对应元素
fmt.Println(slice)
fmt.Println(slice[2]) //创建后的切片从下标0开始
slice[0] = 100 //修改slice的值也会映射到arr1
fmt.Println(slice)
fmt.Println(arr1)
//2.直接定义切片
fmt.Println("直接创建切片")
slice2 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(slice2)
//使用make()函数创建切片
slice3 := make([]int, 3, 5) //创建一个长度为3,但是容量为5的切片,由于没有赋值,会默认为0值
fmt.Println(slice3)
fmt.Println(len(slice3), cap(slice3)) //长度(存储的数据个数),容量(最大能容纳个数)
//4.切片截取
fmt.Println("从slice1里面截取出slice4")
slice4 := slice[0:3]
fmt.Println(slice4)
slice4[0] = 147 //这个操作也会映射到slice
fmt.Println(slice)
//append
slice4 = append(slice4, 1, 2, 3) //通过这个完成对slice4的变长增加
fmt.Println(slice4)
fmt.Println("也可以把一个切片追加到另一个切片后面")
fmt.Println("原来的slice4是", slice4, "slice是", slice)
slice4 = append(slice4, slice...)
fmt.Println("使用slice4 = append(slice4, slice...)")
fmt.Println("追加后的slice4:", slice4)
//创建一个切片的时候会指向一个底层数组,如果是根据数组创建的切片就会指向该数组
//如果扩容之后数组的长度大于了原来的容量,就会指向一个新的底层数组。并且把原来的值拷贝过来。容量是原来的2倍
//如果是根据数组创建的切片,在扩容之后就会与原数组失去联系