Ctrl + B可查看鼠标位置Go函数源码
1.变量
变量用于描述计算机中的数据存储空间,其作用为在计算机内存中保存数据。
变量的声明格式: var 变量名称 类型;例如var age int
就声明了一个叫age的变量其类型为int。默认值为0。
一次性可以声明多个变量,比如var age,num,sum int
可以讲一个变量的值,赋值给另外一个变量,并且变量中原有的旧值被新值所覆盖
1.1自动推导类型
格式:变量名 := 值
例如num := 10
就是自动推导类型,具体num的类型到底是什么,那就要根据等号后面的数值,编译器自行去判断。比如这里赋值为10,那么num就是整型。
也可以进行多个变量一起赋值,比如a,b,c := 1.1,2,3
👇一个小练习:互换两个变量的值。之前我们一般引用第三个变量实现两个变量的值交换,但是go语言可以直接如下这么写
func main() {
num1 := 10
num2 := 20
num1, num2 = num2, num1
fmt.Println(num1, num2)
}
1.2变量命名规范
- 只能由数字,字母,_(下划线)组成
- 不能以数字开头
- 大写字母和小写字母严格区分
- 不能是关键字
- 见名知意
- 驼峰命名法:小驼峰:第一个单词首字母小写,第二个单词首字母大写;大驼峰:单词首字母全大写
- 下划线分割法:多个单词组成的名称,全小写字母书写可以用_分隔,比如first_name
部分关键字如下
2.输出格式
如果我们打算输出一个变量的具体类型,可以用Printf函数,"%T" + 变量名
打印
Println和Print的区别在于加”ln“表示换行输出。
如果打算把数值对应的变量名也打印可以这么写fmt.Println("num1 = " , num1)
;这里面的“,”逗号相当于Java里的 “+”号
Printf:和C语言的printf函数一样,一定要指明输出一个什么类型的值。比如%d表示输出的是一个整型标量中的值。
func main() {
num1 := 10
num2 := 20
num1, num2 = num2, num1
fmt.Println(num1, num2)
fmt.Printf("%d\n", num1) // \n表示换行输出
}
3.输入格式
Go提供了两个输入函数,Scanf()和Scan()。
Scanf()使用方法和C语言的scanf()一样,要先指明输入什么类型的值,再把想赋值的变量写进去用逗号隔开,并加上**&符号(&表示要获取这个变量的内存地址,即取地址符号**)
输入数据后敲回车键表示输入结束
func main() {
var age int
fmt.Println("请输入年龄")
fmt.Scanf("%d", &age)
fmt.Println("age = ", age)
}
我们可以用变量标记一块内存地址,并通过"&变量名"的方式打印出地址,比如fmt.Println(&age)
,要注意地址和变量的值无关,变量的声明只是标记了一块地址,更方便程序员去找到它。如果用Printf函数打印地址记得用"%p"
Scan()的使用比较简单,不需要说明类型,只需要在变量前加一个取地址符就行。比如fmt.Scan(&age)
总结:
Scanf()语法格式:fmt.Scanf(“%_”, &num)
Scan()语法格式:fmt.Scan(&num)
4.计算机进制
进位的规则一定是:逢N进1
-
进制的定义:按进位的原则进行计数的方法叫做进位计数制
-
特点:使用一组固定的数字表示数值的大小。比如十进制是0~9这十个数,逢十进一。
-
进制要素:基数和位权
- 基数:这里的N叫做基数。就是指各种进制计数制中允许选用基本数码的个数。比如10就是十进制的基数,因为逢十进一
- 位权:215 = 2* 102 + 1*101 + 5 *100 其中102,101,100 就是位权
- 按权相加法:让每一位上的数字字符乘以它所代表的权。
-
二进制:只由0和1来表示的数,计算机内部的所有运算操作都是用二进制来表示的
-
十六进制:一般用数字0~9和字母A到F(或a-f)表示
进制转换
二进制转换成十进制,采用按权相加法。比如二进制1011转换成十进制:1011 -> 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20
十进制转二进制,采用“除2取余,逆排序”法,如下图片所示,115转换成二进制就是1110011
5.基础数据类型
位:最小的存储单位,计算机存储的就是二进制0,1,位就是用来存储二进制
字节:基本存储单位,用大写的B来表示,1字节 = 8位
-
整型(%d):分为有符号整型int,无符号整型uint
int包括:正整数,负整数,0;
uint包括:正整数,0
-
浮点类型(%f):用来表示包含小数点的数据,Go语言有float32和float64两种精度,没有double
-
float32精确到小数点后7位,float64精确到小数点后15位。
-
Go语言中涉及到关于数学运算的包中,都要求使用float64这个类型,所以建议多使用float64
-
如果打算保留两位小数输出一个浮点型数时,可以用
%.2f
的格式输出,并且会四舍五入。 -
自动推导类型创建的浮点型默认为float64
-
-
布尔类型(%t):用bool关键字定义,真是true,假是false;默认值为false
-
字符类型(%c打印字符本身,%d打印ASC‖值):用单引号’’ 引起来的单个字符,用byte关键字定义(C语言会用char)
- 每个字符会对应一个ASC‖值,比如’a’ = 97 ; ‘A’ = 65 ;‘0’ = 48
-
字符串类型(%s):用关键字string定义,并用双引号引起来
-
注意:虽然看到的字符串变量只包含一个或一串字符,但隐藏着一个字符串的结束标志**‘\0’**,使用%s输出,只打印’\0’前面的内容
-
测试字符串中的字符个数:用len()函数,比如
fmt.Println(len(str))
,str是提前定义好的string类型的变量 -
一个汉字 = 3字符
-
强制类型转换
比如你支付某件商品,需要付100.5元,商家给你去个零头,付100元就行。那么100.5元是浮点型,100元是整型,这时候就要用强制类型转换。
类型转换:就是将a类型转换成b类型,如下方代码就实现将浮点型转换成整型
func main() {
num := 3.14
var i int = int(num)
fmt.Println(i)
}
也可以直接fmt.Println(int(num))
,输出的结果就是int类型的值:3;而且不会四舍五入。
🎈类型转换时建议将低精度类型往高精度类型转,高转低可能会丢失精度或出现数据溢出
比如:int8 -> int16 -> int32 -> int64 ; float32 -> float64
6.常量
程序运行期间不可以改变的量。常量是不可以打印地址的。
6.1常量定义使用
使用const关键字定义;格式为: const 常量名 类型 = 值
建议对常量命名时对其大写。比如const PI float64 = 3.14
就定义了一个类型为float64的常量叫PI,值是3.14。
当然我们写常量时可以不写它的类型,此时常量的类型由等号后面的值确定。
6.2常量的命名规范
- 只能由数字,字母,_(下划线)组成
- 不能以数字开头
- 建议全部大写,且严格区分大小写
- 不能是关键字
- 见名知意
- 多个单词组成的名称,使用全大写字母书写,中间用下划线分隔
7.运算符
7.1算术运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 加 | 10 + 5 | 15 |
- | 减 | 10 - 5 | 5 |
* | 乘 | 10 * 5 | 50 |
/ | 除 | 10 / 5 | 2 |
% | 取余 | 10 % 3 | 1 |
++ | 自增 | a = 0;a++ | a = 1 |
– | 自减 | a = 1;a– | a = 0 |
注意:
- 在Go语言中,自增自减是没有像C语言那样前自增或前自减的(就是–a这种是没有的)
- 除法和取余运算中,除数不能为0
🎉小练习:输入半径,计算圆的周长和面积并打印出来(PI为3.14)
func main() {
const PI = 3.14
var r float64
fmt.Println("请输入半径:")
fmt.Scan(&r)
//计算圆的周长
p := 2 * PI * r
fmt.Println("圆的周长为:", p)
//计算圆的面积
area := PI * r * r
fmt.Println("圆的面积为:", area)
}
7.2赋值运算符
运算符 | 说明 | 示例 |
---|---|---|
= | 普通赋值 | c = a+b 将a + b表达式结果赋值给c |
+= | 相加后再赋值 | c += a 等价于 c = c + a |
-= | 相减后再赋值 | c -= a 等价于 c = c - a |
*= | 相乘后再赋值 | c *= a 等价于 c = c * a |
/= | 相除后再赋值 | c /= a 等价于 c = c / a |
%= | 求余后再赋值 | c %= a 等价于 c = c % a |
7.3关系运算符
关系运算符的结果是布尔类型的,要么是true(真),要么false(假)
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 判断是否相等 | 4 == 3 | false |
!= | 判断是否不相等 | 4 != 3 | true |
< | 小于 | 4 < 5 | true |
> | 大于 | 5 > 4 | true |
<= | 小于等于 | 4 <= 3 | false |
>= | 大于等于 | 3 >= 2 | true |
7.4逻辑运算符
比如我们要判断一个人的年龄是否在18到30这个区间内,我们不能直接30 > age >18
这么写,我们只能通过逻辑运算符,写成age > 18 && age < 30
才行。
逻辑运算符的结果也是布尔类型。且逻辑运算符的两边一般都是关系运算或者bool类型的值。
注意和C语言的区别:在C语言中是可以把一个整型类型的变量取非的,比如int a = 2;
那么!a的结果是0;但是在Go语言中这么做会报错!Go语言要求逻辑运算符旁边表达式的结果或变量是布尔类型
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则!a为真 |
&& | 与 | a && b | 如果ab都为真,结果才为真,其他都是假 |
|| | 或 | a || b | ab其中有一个为真,则结果为真;都为假结果才为假 |
7.5运算符优先级
运算符可以分为三类:
- 特殊运算符: ()括号 ; 一个. 包名.函数名
- 单目运算符: ! 逻辑非 ; & 取地址
- 双目运算符:算术运算符,关系运算符,&& , || ,赋值运算符
优先级:
-
()括号的优先级最高
-
单目运算符优先级高于双目运算符
-
双目运算符里的优先级:算术运算符 > 关系运算符 >&& > || > 赋值运算符
7.6小练习:闰年的判定
闰年要符合下面两个条件之一
- 年份能够被400整除
- 年份能够被4整除但不能被100整除
func main() {
var year int
fmt.Scan(&year)
b := year%400 == 0 || year%4 == 0 && year%100 != 0
fmt.Println(b)
}
8.分支结构
8.1 if…else结构
它的用法和中文直译过来一样 如果…否则
- 语法格式:
if 条件判断{
代码语句1
} else {
代码语句2
}
注意:其他很多编程语言是要求if后的条件判断表达式要用()括号括起来,但Go语言不需要!
- 执行流程:程序先去看条件判断的结果是否为真,如果为真则执行if{}花括号里的代码语句1,否则执行else{}花括号里的代码语句2
练习1:判断是否成年
题目:如果年龄大于等于18,输出"已成年",否则输出"未成年"
func main() {
age := 18
if age >= 18 {
fmt.Println("已成年")
} else {
fmt.Println("未成年")
}
}
练习2:奇偶数判断
题目:输入一个数字,判断是否是“偶数”,如果是,输出“该数是偶数”,否则输出“该数是奇数”
func main() {
var num int
fmt.Scan(&num)
if num%2 == 0 {
fmt.Println("该数是偶数")
} else {
fmt.Println("该数是奇数")
}
}
练习3:公交
题目:输入公交卡当前的余额,如果余额大于等于2元,就可以上公交车;上车后如果空座位的数量大于0,就可以坐下,否则只能站着。
func main() {
var money float64
fmt.Scan(&money)
if money >= 2 {
fmt.Println("欢迎乘车")
var count int
fmt.Scan(&count)
if count > 0 {
fmt.Println("请在空座位坐下")
} else {
fmt.Println("只能站着")
}
} else {
fmt.Println("余额不足,请投币")
}
}
练习3里涉及到了if语句的嵌套使用,也就是说一个if…else语句是可以嵌在另一个if…else语句里面的。
8.2 if…else if结构
- 基本语法如下:
if 条件判断①{
代码段①
} else if 条件判断②{
代码段②
} else if 条件判断③{
代码段③
} ... {
} else {
代码段n
}
- 执行流程:条件判断① 成立则执行 代码段①然后跳出if…else if整个结构,否则执行条件判断②,成立就执行 代码段②。以此类推。
练习:学生成绩
题目:成绩大于等于90:A等 ;成绩大于等于80且小于90:B等 ; 成绩大于等于70且小于80:C等;成绩大于等于60且小于70:D等 ;成绩小于60:E等
func main() {
var score float64
fmt.Scan(&score)
if score >= 90 {
fmt.Println("A")
} else if score >= 80 {
fmt.Println("B")
} else if score >= 70{
fmt.Println("C")
} else if score >= 60{
fmt.Println("D")
} else {
fmt.Println("E")
}
}
8.3 switch结构
- 语法格式如下
switch 变量或表达式 {
case 值1: 代码段①
case 值2: 代码段②
...
default: 代码段n
}
- 执行流程:变量或表达式对应的值是几,就去执行相应case语句后的代码段;
需要注意的是,go语言的switch语句和C语言的不一样的点在于,go语言的不需要加break关键字来表示一个case结束。
说一些其他的点:
- switch后面的变量或表达式可以不写
- case后面可以不是具体的值,还可以是条件判断语句,这点很重要
练习:学生成绩
上面用if语句实现了这个案例,这次用switch语句实现
题目:成绩大于等于90:A等 ;成绩大于等于80且小于90:B等 ; 成绩大于等于70且小于80:C等;成绩大于等于60且小于70:D等 ;成绩小于60:E等
func main() {
var score float64
fmt.Scan(&score)
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
case score >= 60:
fmt.Println("D")
default:
fmt.Println("E")
}
}
8.4 switch和if综合案例
题目:用户输入年份,再输入月份,输出该月的天数。(需要考虑闰年)
func main() {
var year int
var month int
var day int
fmt.Println("请输入年份")
fmt.Scan(&year)
fmt.Println("请输入月份")
fmt.Scan(&month)
//1.判断月份是否正确
if month >= 1 && month <= 12{
//2.如果1,3,5,7,8,10,12月,天数为31天
switch month {
case 1:
day = 31
case 3:
day = 31
case 5:
day = 31
case 7:
day = 31
case 8:
day = 31
case 10:
day = 31
case 12:
day = 31
//3.闰年的2月有29天,否则为28天
case 2:
if year % 400 == 0 || year % 4 == 0 && year % 100 != 0{
day = 29
} else {
day = 28
}
//4.其他月份是30天
default:
day = 30
}
fmt.Println("天数是:",day)
} else {
fmt.Println("输入月份错误!")
}
}
我们会发现,上面的代码中 day = 31出现过多,我们可以优化一下,此时我们可以用fallthrough关键字。
8.5 fallthrough
fallthrough的作用在于:如果在switch语句里找到匹配的case语句去执行,发现里面的代码是fallthrough,那么程序就会接着执行下一个case语句,也可以通过此方法执行default语句。
上面的练习优化后的代码
func main() {
var year int
var month int
var day int
fmt.Println("请输入年份")
fmt.Scan(&year)
fmt.Println("请输入月份")
fmt.Scan(&month)
//1.判断月份是否正确
if month >= 1 && month <= 12 {
//2.如果1,3,5,7,8,10,12月,天数为31天
switch month {
case 1:
fallthrough
case 3:
fallthrough
case 5:
fallthrough
case 7:
fallthrough
case 8:
fallthrough
case 10:
fallthrough
case 12:
day = 31
//3.闰年的2月有29天,否则为28天
case 2:
if year%400 == 0 || year%4 == 0 && year%100 != 0 {
day = 29
} else {
day = 28
}
//4.其他月份是30天
default:
day = 30
}
fmt.Println("天数是:", day)
} else {
fmt.Println("输入月份错误!")
}
}
9.循环结构
Go语言的循环结构没那么复杂,只有一个for循环结构,没有while和do-while。
9.1 for循环基本结构
基本语法如下:
for 初始化变量 ; 判断条件 ; 修正变量 {
代码段(循环体)
}
- 初始化变量:对一个变量进行初始化,以记录循环次数
- 判断条件:看条件是否成立,如果成立进入花括号{},执行循环体一次;不成立则循环结束
- 修正变量:改变变量的值,再去执行判断条件,看是否条件是否还成立,如果符合,再去执行循环体一次
具体执行流程如下图:① -> ② -> ④ -> ③ -> ② -> ④ -> ③…直到②不成立为止
练习:用for循环打印0-9
func main() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
注意这里的i只在for结构里有用,出了结构就不能再使用了
练习:求1-100数字之和
func main() {
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
fmt.Println(sum)
}
练习:求1-100的偶数和
func main() {
sum := 0
for i := 1; i <= 100; i++ {
if i%2 == 0 {
sum += i
}
}
fmt.Println(sum)
}
9.2 break语句
有时候使用循环结构时,即使条件满足,我也想强制跳出结束整个循环,这时候就要用到break关键字。
break作用:结束当前循环,后面的代码也不会再执行
比如本来我要打印0-9这些数,现在我突然改想法,打印到3(不算3这个数)就不打印了,除了可以更改条件判断语句外,我们就可以引用break关键字。具体如下:
func main() {
for i := 0; i < 10; i++ {
if i == 3 {
break
}
fmt.Println(i)
}
}
break常用在无法判断for要循环多少次的情况。可以看下面的案例进行理解。
案例:用户名和密码
题目:要求用户输入用户名和密码,只要不是用户名为admin,密码为888888,就一直让用户重新输入
解析:我们无法判断用户到底要输入多少次才能输入正确,这时候我们就要用到死循环和break。
死循环:就是一直循环,无法终止。只能用break跳出。就是for后面直接跟{},{}里加循环体代码
func main() {
var userName string
var userPwd string
for {
fmt.Println("请输入用户名:")
fmt.Scan(&userName)
fmt.Println("请输入密码:")
fmt.Scan(&userPwd)
//对用户名和密码进行判断
if userName == "admin" && userPwd == "888888" {
fmt.Println("输入正确")
break //正确就跳出结束循环
} else {
fmt.Println("输入的用户名或密码错误,请重新输入")
}
}
}
现在我改一下题目:如果用户输入错误次数超过三次(即第三次还输入错误),就提示“输入错误信息次数太多”,并结束整个程序。
func main() {
var userName string
var userPwd string
var count int //记录用户输错的次数
for {
fmt.Println("请输入用户名:")
fmt.Scan(&userName)
fmt.Println("请输入密码:")
fmt.Scan(&userPwd)
//对用户名和密码进行判断
if userName == "admin" && userPwd == "888888" {
fmt.Println("输入正确")
break
} else {
count++
if count >= 3 {
fmt.Println("输入错误信息次数太多")
break
}
fmt.Println("输入的用户名或密码错误,请重新输入")
}
}
}
9.3 continue语句
continue作用:结束本轮循环,然后进行循环条件的判断,如果成立则进行下一轮循环,否则退出循环。
注意continue是结束的本轮循环,会继续进行条件判断;而break是跳出结束整个循环,不会再进行条件判断。
比如我要用continue实现:输入1-5这几个数字,而3除外。
func main() {
for i := 1; i <= 5; i++ {
if i == 3 {
continue
}
fmt.Println(i)
}
}
9.4 循环嵌套
循环体里有循环结构就是循环嵌套
比如一个人一天吃三顿饭,每次吃饭时要说“我要吃饭”,并重复说三天。
func main() {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Println("我要吃饭")
}
}
}
再比如我要输出一个矩形,一行有5个*,共5行。
func main() {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
fmt.Print("*")
}
fmt.Println()
}
}
9.5 循环综合练习
练习:计算营业额
题目:2006年营业额80000元,每年增长25%,请问按此增长速度,到哪一年营业额将达到20万元?
func main() {
year := 2006
var money float64
for money = 80000; money <= 200000; money *= 1.25 {
year++
}
fmt.Println(year)
}
练习:水仙花数
题目:找出100-999间的水仙花数
水仙花数:是指一个三位数,他的每位数字的立方和等于其本身
func main() {
for num := 100; num <= 999; num++ {
a := num / 100
b := num % 100 / 10 //或 b:= num / 10 % 10
c := num % 10
if a*a*a+b*b*b+c*c*c == num {
fmt.Println(num)
}
}
}
练习:乘法口诀表
func main() {
for i := 1; i < 10; i++ {
for j := 1; j < 10; j++ {
fmt.Print(i, "*", j, "=", i*j, " ")
}
fmt.Println()
}
}
这是矩形的,下面打印个三角形的
func main() {
for i := 1; i < 10; i++ {
for j := 1; j <= i; j++ {
fmt.Print(i, "*", j, "=", i*j, " ")
}
fmt.Println()
}
}