Day02 Go语言流程控制、数组、切片
上午01 上节回顾
day01回顾:
Go:静态编译型语言
Go:极高的开发效率 同时很好的运行性能,高并发能力
安装编译器
go env
GOROOT=D:\Go
GOPATH=D:\GoWork
GOPATH下目录结构
bin
pkg
src\s9\day01
文件名可以不叫main.go
go执行命令
方式1 go build -o 自定义可执行文件名
调用可执行文件
方式2 go run go程序文件名.go
基本语法:
变量和变量赋值
方式1: 先声明再赋值
var 变量名 变量类型
var x int 开辟空间,空间已确定
x = 100
方式2:声明并赋值
var y = 200
方式3: 简易赋值
z:=300
方式4: 多个变量的赋值:
var a,b,c = 100,”hello”,true
匿名变量
var _,b,c = 100,”hello”,true
变量命名规范
强制 必须数字、字母、下划线
不能以数字开头
不能是保留字:赋予特定功能的字
建议:驼峰,见名知意,区分大小写
语句分隔符:
换行和分号,推荐换行
注释:
// 单行, /*多行*/
基本数据类型:(值类型)
int float 进制
12 3.14
bool
true false
string
“”
冯诺依曼 存储式编程
根据存储分两类:
值类型 有默认值
引用类型
package main
import "fmt"
func main() {
var x int // 开辟空间,有默认值
fmt.Println(x)
x = 10
fmt.Println(x)
var s string
fmt.Println(s)
fmt.Printf("%#v\n",s)
var b bool
fmt.Println(b)
}
零值:每一个数据类型下有且只有一个布尔值为false的值,这个值称为这个类型的零值
整型:0
字符串:“”
布尔值:false
当声明一个值类型变量未赋值时,零值会作为该变量的默认值
字符串:
双引号标识
var s=”hello world”
len() 字符长度
基本操作:
索引: s[2]
切片:s[2:4] //顾头不顾尾,字符串切出来还是字符串
转义符号: \n \\
反引号: `` 多行打印
内置方法 :字符串 .方法()
strings.ToUpper(s) strings.ToLower(s) strings.Contains(s) Strings.HasPrefix(s) strings.HasSuffix(s) strings.Trim(s,” “) // 返回字符串 strings.Index(s,“world”) 查索引 //未找到,返回-1 strings.LastIndex(s,”l”) 从后往前查 var s = “1 2 3 4 5” var arr =strings.Split(s,” “) //返回值是一个数组 [“1”,”2”,”3”,”4”,”5”] strings.Join(arr,”+”) //传入数组
? rootroot hello root 咋去除?
只去除行首第一个root
var str1 = "rootroot test root" var str2 =strings.TrimPrefix(str1,"root") fmt.Println(str2)
运算符:
科学计算运算符
fmt.Println(1+1) fmt.Println(12%2 == 0)
奇数 偶数
运算符: 自增 ++ 仅限于自加1
赋值运算
//运算符 ++ var a = 10 //a=11 //a = a+1 a+=1 //a=a+1 fmt.Println(a)
逻辑运算符: 与&& 或|| 非!
类型转换:
x:=strconv.Itoa(112)
y,_:=strconv.Atoi(“2000”)
上午02 流程控制语句
分两类
分支语句
循环语句
分支语句:
单分支
双分支
多分支
if 分支语句
if 语法格式:
单分支
if 表达式{
语句体
}
双分支
if 表达式{
语句体
}else {
语句体
}
多分支
if 表达式{
语句体
}else if 表达式 {
语句体
}else{
语句体
}
最后的else不是必须的
示例
goland小技巧:
Ctrl+Alt+L 格式化代码
Shift+Tab 左移
package main
import "fmt"
func main() {
/* var user string
var pwd string
fmt.Print(">>>")
fmt.Scanln(&user, &pwd)*/
//单分支语句
/* if user == "rain" && pwd == "123" {
fmt.Println("登录成功")
}*/
//双分支语句
/* if user == "rain" && pwd == "123" {
fmt.Println("登录成功")
}else{
fmt.Println("用户名或者密码错误!")
}*/
//多分支语句
var score int
fmt.Scanln(&score)
if score>100 || score <0 {
fmt.Println("输入的成绩应该在0-100之间")
}else if score>=90 {
fmt.Println("成绩优秀")
}else if score >=80 {
fmt.Println("成绩良好")
}else if score >=60 && score<80 {
fmt.Println("成绩及格")
}else {
fmt.Println("成绩不及格")
}
fmt.Println("OK")
}
switch语句
只做比对
switch 变量 {
case 具体值:
语句A
case 值:
语句B
case 值:
语句C
default:
...
}
可以没有default语句块
示例
package main
import "fmt"
func main() {
var week int
fmt.Scanln(&week)
switch week {
case 0 :
fmt.Println("星期日")
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
case 4:
fmt.Println("星期四")
case 5:
fmt.Println("星期五")
case 6:
fmt.Println("星期六")
}
}
空间换时间,建个表查
对比
1、switch比if else更为简洁
2、执行效率更高
3、到底使用哪一个选择语句,代码环境有关,如果是范围取值,则使用if else语句更为快捷;如果是确定取值,则使用switch是更优方案。
练习题:通过输入范围,判断星座
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
var brith string
fmt.Printf("请输入生日年月日,格式2022-01-16: ")
fmt.Scanln(&brith)
brithSlice:=strings.Split(brith,"-")
month :=brithSlice[1]
day :=brithSlice[2]
var date =month+"."+ day
dateFloat,_ :=strconv.ParseFloat(date,64)
if dateFloat >=3.21 && dateFloat<4.19 {
fmt.Println("白羊座")
}else if dateFloat>=4.19 && dateFloat<5.20 {
fmt.Println("金牛座")
}else{
fmt.Println("xx座")
}
}
另外的思路
var brith string
fmt.Printf("请输入生日年月日,格式2022-01-16: ")
fmt.Scanln(&brith) //2000-03-16 ---> ["2000" "3" "16"]
var arr = strings.Split(brith,"-")
fmt.Println("arr",arr)
fmt.Println("month",arr[1]) //"03"
fmt.Println("day",arr[2]) //"16"
var arr2 = []string{arr[1],".",arr[2]}
fmt.Println(strings.Join(arr2,"")) //返回字符串,还需要再转float型
Join输入切片类型 注意[]string
var arr2 = []string{arr[1],".",arr[2]}
fmt.Println(strings.Join(arr2,"")) //返回字符串,还需要再转float型
省去变量直接输出
brithSlice:=strings.Split(brith,"-") var brithStr = brithSlice[1]+"."+brithSlice[2] brithFloat,_:=strconv.ParseFloat(brithStr,64) fmt.Println(brithFloat)
测试结果
请输入生日年月日,格式2022-01-16: 2021-03-22 3.22 白羊座
下午01 循环
多分支语句练习
// for 循环
for 表达式 {
语句体
}
有限循环三要素:
1、声明初始化变量
2、比较表达式
3、步进语句
package main
import "fmt"
func main() {
fmt.Println("hello world")
fmt.Println("hello world")
fmt.Println("hello world")
}
无限循环
退不出循环了
D:\GoWork\src\gitee.com\zhutao2014\s9\day02\05循环语句\main.go
package main
import "fmt"
func main() {
//无限循环
for true {
var user string
var pwd string
fmt.Print(">>>")
fmt.Scanln(&user, &pwd)
if user == "rain" && pwd == "123" {
fmt.Println("登录成功")
}else{
fmt.Println("用户名或者密码错误!")
}
}
}
有限循环(三要素)
package main
import "fmt"
func main() {
//有限循环 1、声明初始化变量 2、比较表达式 3、步进语句
var n = 0
for n<10 {
//fmt.Println("hello world")
fmt.Println(n)
n++
}
}
课堂练习1 + ...+ 100
package main
import "fmt"
func main() {
//课堂练习
var n=1
var sum = 0
for n<101 {
sum+=n
n++
}
fmt.Println(sum)
}
打断点
第二次 点击执行蓝条
练习打印 1-100中所有的偶数
package main
import "fmt"
func main() {
var n = 0
for n < 101 {
if n%2 == 0 {
fmt.Println(n)
}
n++
}
}
三要素for循环
package main
import "fmt"
func main() {
var n = 1 //初始化变量
for n < 101 { //比较表达式
fmt.Println(n)
n++ //步进语句
}
//三要素循环
for n4:=1;n4<100;n4++ {
fmt.Println(n)
}
}
退出 break和continue
1、正常退出
2、条件退出
break和continue
break退出整个循环
continue退出当次循环
练习思考:打印0-88 一直打印 88
//打印0-88 一直打印 88
var a = 0
for a<100 {
fmt.Println(a)
if a == 88 {
continue
}
a++
}
}
循环嵌套练习
下午02 容器数据类型
数组
数组声明
声明语法
var 数组名 [元素数量]元素类型
package main
import (
"fmt"
"reflect"
)
func main() {
// 数组 先声明 再赋值
var arr [3]int //数组是一个值类型
fmt.Println(arr) // [0 0 0]
//支持索引和切片
fmt.Printf("%d %p\n",arr,&arr)
fmt.Println(arr[0],&arr[0])
fmt.Println(arr[1],&arr[1])
fmt.Println(arr[2],&arr[2])
arr[0]=10
arr[1]=11
arr[2]=12
//打印类型
fmt.Println(arr,reflect.TypeOf(arr))
}
数组赋值
package main
import (
"fmt"
"reflect"
)
func main() {
//声明并赋值
var names = [3]string{"yuan","rain","alvin"}
fmt.Println(names) //[yuan rain alvin]
//不限长赋值
var names2 = [...]string{"yuan","rain","alvin","eric"}
fmt.Println(names2,reflect.TypeOf(names2)) //[yuan rain alvin]
//索引赋值
var names3 = [3]string{0:"张三",2:"王五"}
fmt.Println(names3,len(names3))
}
遍历数组 3种
//循环数组
var names=[]string{"yuan","rain","alvin","eric"}
//for i:=0;i
练习 a开头的 改成纯大写的
package main
import (
"fmt"
"strings"
)
func main() {
//range 循环
var names = [...]string{"yuan","rain","alvin","eric","alex"}
for i:=range names {
//if strings.HasPrefix(names[i],"a") {
// names[i]=strings.ToUpper(names[i])
//}
if names[i][0] == 'a' {
names[i]=strings.ToUpper(names[i])
}
}
fmt.Println(names)
}
range遍历出索引和值
package main
import (
"fmt"
"strings"
)
func main() {
//range 循环
var names = [...]string{"yuan","rain","alvin","eric","alex"}
for i,name:=range names {
if strings.HasPrefix(name,"a") {
names[i]=strings.ToUpper(name)
}
}
fmt.Println(names)
}
打印结果:
[yuan rain ALVIN eric ALEX]
切片
创建切片
package main
import (
"fmt"
"reflect"
)
func main() {
var arr = [5]int{10,11,12,13,14}
var s1 = arr[1:4]
fmt.Println(s1,reflect.TypeOf(s1)) //[11 12 13] []int
var s2 = arr[2:5]
fmt.Println(s2,reflect.TypeOf(s2)) //[12 13 14]
fmt.Println(":::",s1,s2)
}
打印结果
[11 12 13] []int
[12 13 14] []int
::: [11 12 13] [12 13 14]
切片的地址:
修改切片
package main
import (
"fmt"
"reflect"
)
func main() {
var arr = [5]int{10,11,12,13,14}
var s1 = arr[1:4]
fmt.Println(s1,reflect.TypeOf(s1)) //[11 12 13] []int
var s2 = arr[2:5]
fmt.Println(s2,reflect.TypeOf(s2)) //[12 13 14] []int
//arr[2] = 120
fmt.Println(":::",s1,s2) //::: [11 12 13] [12 13 14]
//从切片上切
//var s3 = s2[0:5] //panic: runtime error: slice bounds out of range [:5] with capacity 3
var s3 = s2[0:2]
s3[0]=1000
fmt.Println(s3) //[1000 13]
fmt.Println(":::",s1,s2,s3) //::: [11 1000 13] [1000 13 14] [1000 13]
}
打印长度和容量
package main
import (
"fmt"
"reflect"
)
func main() {
var arr = [5]int{10,11,12,13,14}
var s1 = arr[1:4]
var s2 = arr[2:5]
fmt.Println(":::",s1,s2) //::: [11 12 13] [12 13 14]
var s3 = s2[0:2]
s3[0]=1000
fmt.Println(":::",s1,s2,s3) //::: [11 1000 13] [1000 13 14] [1000 13]
//打印长度和容量
fmt.Println(":::",s1,len(s1),cap(s1))
fmt.Println(":::",s2,len(s2),cap(s2))
fmt.Println(":::",s3,len(s3),cap(s3))
}
打印结果:
::: [11 12 13] [12 13 14]
::: [11 1000 13] [1000 13 14] [1000 13]
::: [11 1000 13] 3 4
::: [1000 13 14] 3 3
::: [1000 13] 2 3
练习题
package main
import (
"fmt"
"reflect"
)
func main() {
var a=[...]int{1,2,3,4,5,6}
a1:=a[0:3] //[1 2 3] 3 6
a2:=a[0:5] //[1 2 3 4 5] 5 6
a3:=a[1:5] //[2 3 4 5] 4 5
a4:=a[1:] //[2 3 4 5 6] 5 5
a5:=a[:] // [1 2 3 4 5 6] 6 6
a6:=a3[1:2] //[3] 1 4
fmt.Println("===")
fmt.Println(a1,len(a1),cap(a1))
fmt.Println(a2,len(a2),cap(a2))
fmt.Println(a3,len(a3),cap(a3))
fmt.Println(a4,len(a4),cap(a4))
fmt.Println(a5,len(a5),cap(a5))
fmt.Println(a6,len(a6),cap(a6))
}
下午03
切片声明
切片声明3种方式(从数据切片,使用make创建,使用append生成新切片)
1 从数据切片
package main
import (
"fmt"
"reflect"
)
func main() {
var arr = [5]int{10,11,12,13,14}
fmt.Println(arr,reflect.TypeOf(arr)) //[10 11 12 13 14] [5]int
var s1 = arr[1:4]
fmt.Println(s1,reflect.TypeOf(s1)) //[11 12 13] []int
var s2 = arr[2:5]
fmt.Println(s2,reflect.TypeOf(s2)) //[12 13 14]
//arr[2] = 120
fmt.Println(":::",s1,s2) //::: [11 12 13] [12 13 14]
}
2使用make函数
package main
import "fmt"
func main() {
//切片:引用类型,当只声明,未赋值,不开辟空间
var s3 []int
//s3[0] = 10
fmt.Println(s3)
//make函数
var s4 = make([]int,3,5)
fmt.Println(s4)
s5:=s4[0:5]
fmt.Println(s5)
}
打印结果
[]
[0 0 0]
[0 0 0 0 0]
切片扩容 append
package main
import "fmt"
func main() {
var s []int
//s1:=append(s,1)
//s1:=append(s,1,2,3,4,5)
s1:=append(s,[]int{1,2,3,4,5}...)
fmt.Println(s1)
}
打印结果
[1 2 3 4 5]
append案例1
package main
import "fmt"
func main() {
//案例1
a:=[]int{12,23,34}
fmt.Println(len(a))
fmt.Println(cap(a))
b:=append(a,45)
fmt.Println(b)
a[0]=1000
fmt.Println(a)
fmt.Println(b)
}
打印结果: 注意:b扩容后,底层数据已经变化,a和b底层已经不是同一个数组
3
3
[12 23 34 45]
[1000 23 34]
[12 23 34 45]
append案例2
package main
import "fmt"
func main() {
var s []int
//s1:=append(s,1)
//s1:=append(s,1,2,3,4,5)
s1:=append(s,[]int{1,2,3,4,5}...)
fmt.Println(s1)
//案例2
c:=make([]int,3,5)
d:=append(c,100)
fmt.Println(c,d)
c[0] = 1000
fmt.Println(d)
}
打印结果:
[0 0 0] [0 0 0 100]
[1000 0 0 100]
图解
面试题
package main
import "fmt"
func main() {
//面试题
arr := [4]int{10,20,30,40}
s1:=arr[0:2] //[10 20]
s2:=s1 //[10 20]
s3:=append(append(append(s1,1),2),3)
//s3 [10 20 1 2 3]
s1[0]=1000
fmt.Println(s2[0],s2) //[1000 20]
fmt.Println(s3[0],s3) //[10 20 1 2 3]
}
练习题
思考:这样写可以不?
package main
import "fmt"
func main() {
var a = []int{1,2,3,4}
s1:=a[:2] //[1,2]
s2:=a[2:] //[3,4]
fmt.Println(append(append(s1,100,),s2...))
//[1,2,100] 此时数组a为[1,2,100,4] 切片s2 已经为[100,4]
//[1,2,100,3,4] x 答案为[1 2 100 100 4]
}
作业
(1) 计算 1 - 2 + 3 - 4 + ... + 99 中除了88以外所有数的总和?
(2) 求1+2!+3!+4!+……+10!的和
(3) 程序随机内置一个位于一定范围内的数字作为猜测的结果,由用户猜测此数字。用户每猜测一次,由系统提示猜测结果:太大了、太小了或者猜对了,直到用户猜对结果或者猜测次数用完导致失败。设定一个理想数字比如:66,让用户三次机会猜数字,如果比66大,则显示猜测的结果大了;
如果比66小,则显示猜测的结果小了;只有等于66,显示猜测结果正确,退出循环。最多三次都没有猜测正确,退出循环,并显示‘都没猜对,继续努力’。
(4) 计算索引为10的斐波那契数列对应的值(斐波那契数列指的是一个数列 0, 1, 1, 2, 3, 5, 8, 13,特别指出:第0项是0,第1项是第一个1。从第三项开始,每一项都等于前两项之和)
(5) 打印菱形小星星
作业2 阶乘
思路:乘法优先级高,
1、定义初始乘积为1,先算1*2*3*...*10的积
2、定义初始和为0,再把乘积相累加。
package main
import "fmt"
func main() {
//1 - 10的阶乘和
sum :=0
product:=1
for i:=1;i<11;i++{
//1 求乘积
product*=i
//fmt.Println(product)
//2 求和
sum+=product
}
fmt.Println(sum)
}
作业3 猜数字
package main
import (
"fmt"
"strconv"
)
func main() {
//2 猜数字,猜对退出
var num = 66
for i:=0;i<3;i++ {
var choice string
fmt.Print("输入1-100数字:")
fmt.Scanln(&choice)
choiceInt,err:=strconv.Atoi(choice)
if err !=nil {
fmt.Println("非法输入")
}else if choiceInt > num {
fmt.Println("猜大了")
}else if choiceInt < num {
fmt.Println("猜小了")
}else if choiceInt == num {
fmt.Println("恭喜你,猜对了")
break
}
if i==2 {
fmt.Println("都没猜对,继续努力")
}
}
}
改进
package main
import (
"fmt"
"strconv"
)
func main() {
//2 猜数字,猜对退出
var num = 66
for i:=0;i<3;i++ {
var choice string
fmt.Print("输入1-100数字:")
fmt.Scanln(&choice)
choiceInt,err:=strconv.Atoi(choice)
if err !=nil {
fmt.Printf("非法输入,已输入%d次\n",i+1)
}else if choiceInt > num {
fmt.Printf("猜大了,已输入%d次\n",i+1)
}else if choiceInt < num {
fmt.Printf("猜小了,已输入%d次\n",i+1)
}else if choiceInt == num {
fmt.Println("恭喜你,猜对了")
break
}
if i==2 {
fmt.Println("都没猜对,继续努力")
}
}
}
作业4 斐波那契数列
方法1 实现
package main
import "fmt"
func main() {
a:=0
b:=1
var sum int
for i:=2;i<11;i++ {
sum=a+b
b,a = sum,b
}
fmt.Println(sum)
}
方法2 切片实现
第0项是0,第1项是第一个1
package main
import "fmt"
func main() {
// 会多次开辟空间
/* slice := []int{0, 1}
for i := 0; i <= 11; i++ {
if i == 0 {
slice = []int{0}
continue
} else if i == 1 {
slice = []int{0, 1}
continue
} else if i >= 2 {
slice = append(slice, slice[i-1]+slice[i-2])
}
}
fmt.Println(slice[10])*/
// 一次开辟好切片空间
slice := make([]int, 11)
for i := 0; i < 11; i++ {
slice[1]=1
slice[2]=1
if i>=2 {
slice[i]=slice[i-1]+slice[i-2]
}
}
fmt.Println(slice[10])
}