go语言基础(一):数据类型、常量、控制语句、循环、函数定义
1. 变量的定义和使用
语法:var 变量名 类型名 = 数值
- 如果当变量仅定义但是不对它进行初始化的话,那么默认是0
func main() {
var PI float64 = 3.14159
var r float64 = 2.5
var s float64 = PI * r * r
var l float64 = PI * r * 2
fmt.Println("s = ", s)
fmt.Println("l = ", l)
}
- 打印变量类型:
使用fmt.Printf("%T", 变量)
- 变量自动推导:`变量名 := 变量值. 非常无敌常用!!!
- 注意:不能在全局变量的定义中使用自动推导
a := 10
b := "hello"
c := 3.14 // 默认是float64
- 多重定义
- 多重定义可以有多种类型同时存在
func main() {
a,b,c := 10, 3.14, "hello"
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b)
fmt.Printf("%T\n", c)
}
- 匿名变量:相当于一个占位,不可以打印它的值
a,_,c := 10, 3.14, "hello"
常配合函数多个返回值使用
- 格式化输入输出(同c语言)
fmt.Printf("%占位符", 变量)
%d 十进制
%f 浮点型数据,默认保留六位小数,如果写%.2f,那么会对小数进行保留2位,四舍五入
%s 字符串
%t 布尔类型
2. 输入
语法1:fmt.Scan(&变量名)
语法2:fmt.Scanf("%占位符", &变量名)
func main() {
var a int
fmt.Scan(&a)
fmt.Println("a = ", a)
}
// 键入
heklo
// 输出
a = 0
以上代码中,输入123,结果正确显示出a=123。
如果当输入不正确时,即类型无法与int类型相匹配的时候,则会将a的值设为默认的0
- 所有的输入和输出以换行或者空格分隔
3. bool类型
bool类型的值在go中为true或false,与c++区分0和1
若不给bool类型赋值,那么默认为false
4. 其他类型
1. 浮点类型
float32 精准位数是7位
float64 精准位数是15位
- 默认自动推到是float64
2. 字符类型
关键字是byte,是uint8的别名,大小占1个字节,是无符号的
var ch byte = 'a'
3. 字符串类型
关键字是string,长度固定为16字节,打印它的占位符是%s
func main() {
var str string = "你好"
fmt.Println("str =", str)
// 大小为6的原因是一个汉字在其中占3个字节的大小
fmt.Println("str =", len(str))
// string的变量不管有多长永远占6个字节
fmt.Println("str =", unsafe.Sizeof(str))
str = "hello world"
fmt.Println("str =", unsafe.Sizeof(str))
}
输出:
str = 你好
str = 6
str = 16
str = 16
5. 格式化输出
func main() {
a := 123
// 十进制
fmt.Printf("a =%d\n", a)
// 二进制
fmt.Printf("a =%b\n", a)
// 八进制
fmt.Printf("a =%o\n", a)
// 十六进制 a-f小写
fmt.Printf("a =%x\n", a)
// 十六进制 A-F大写
fmt.Printf("a =%X\n", a)
}
6. 常量的定义
语法:const 变量名 类型 = 值
-
常量不能修改它的值
-
不允许获取常量的地址
-
定义常量是不允许使用
:=
自动推导 -
在定义常量时可以省略数据类型
const PI = 3.14 // 小数默认是float64
-
字面常量,在程序中不知道名字的一些常量,不能修改值,不能获取地址
func main() {
// 常量的定义
const a int = 10
// a = 20 不能修改
// fmt.Println(&a)
b := a + 100
fmt.Println(b)
// 字面常量
fmt.Println(123)
fmt.Println(1.5)
fmt.Println("hello")
}
7. 枚举 iota
iota默认的值为0,第一行的值为0, 每换一行,值+1
如果是在同一行调用多次iota,那么他们就会是相同的值
func main() {
// 建议在定义常量或枚举时,标识符使用大写字母,用于和变量区分
//const( // 注意这里是圆括号
// a = iota
// b = iota
// c = iota
//)
const( // 注意这里是圆括号
a = iota
b,c = iota, iota
)
// 简写法
const(
A = iota
B
C
)
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(A)
fmt.Println(B)
fmt.Println(C)
}
- 建议定义常量或枚举时使用大写字母
- 不要隔行写iota,这样的值会不好看出来
8. 运算符
注意:在go语言中没有前置++或–,只有后置的
- go语言中不允许 ++和-- 参与表达式计算
a = 1 + a++
不允许!
- ++ 和 – 如果在表达式中出现,那么在不同的平台下会出现二义性的问题
9. 类型转换
在go语言中,不同的类型之间不能进行计算,所以为了进行计算要进行类型转换
语法:数据类型(变量)
或数据类型(表达式)
- 建议在数据类型转换时进行类型的提升
func main() {
a := 10
b := 2.5
// 此处不允许进行计算,因为a是int型,b是float64的
// fmt.Println(a/b)
fmt.Println(float64(a) / b)
c := 12.5
d := 3.4
fmt.Println(int(c / d))
}
10. 运算符优先级
从上至下运算符优先级依次降低
- 特殊运算符
- 单目运算符
- 双目运算符
- 算数运算符
*
,/
,%
+
,-
- 关系运算符
- 逻辑运算符
&&
||
- 赋值运算符
- 算数运算符
11. 流程控制语句
11.1 if判断
没什么可说的,简单写一下语句就行了
func main() {
var score int
fmt.Scan(&score)
if score > 700 {
fmt.Println("我要上清华")
} else if score > 680 {
fmt.Println("我要上太原理工")
} else {
fmt.Println("我要上蓝翔")
}
}
11.2 switch语句
switch 变量 {
case 值:
语句
fallthrough // 如果执行了本判断下的语句,那么再进行下面的判断
case 值:
语句
fallthrough // 如果执行了本判断下的语句,那么再进行下面的判断
case 值:
语句
fallthrough // 如果执行了本判断下的语句,那么再进行下面的判断
}
如果使用了过多的fallthrough,会使语句不便读,可以将语句修改为
在case中将多个值用逗号进行分割
switch 变量 {
case 1, 3, 5, 7, 9:
语句
case 2, 4, 6, 8, 10:
语句
}
switch不仅仅可以做单个值的直接等于判断,也可以进行范围的判断
此时注意switch后面不跟一个变量
switch {
case 条件表达式:
语句
case 条件表达式:
语句
case 条件表达式:
语句
default:
语句
}
12. 循环
- go语言中没有while和do-while, 使用的是for
for 表达式;表达式;表达式 {
语句
}
死循环:for后面不写表达式,直接写括号
for {
语句
}
- for的范围遍历
for index, val := range 集合名 {
语句
}
13. 无条件跳转语句 goto
语法:goto 跳转点
。 跳转点名:
func main() {
fmt.Println("hello1")
fmt.Println("hello2")
goto FLAG // 跳转动作
fmt.Println("hello3")
FLAG: // 设置跳转点
fmt.Println("hello4")
fmt.Println("hello5")
}
14. 函数
14.1 普通函数
语法:
func 函数名(参数列表)(返回值列表) {
代码体
return 值
}
最简单的一个函数定义:
func add(a int, b int) int {
sum := a + b
return sum
}
func main() {
fmt.Println(add(10, 20))
}
14.2 不定参函数
func 函数名(参数名 ...参数类型) {
语句
}
- 不定参函数的基本使用
// arr 是一个切片类型,其中的数据类型是函数定义时指定的类型如果指定的是...interface{},那么就是任意类型
func test1(arr ...int) {
fmt.Println(arr)
fmt.Printf("%T\n", arr)
// arr 是从下标0开始的
fmt.Println(arr[0])
fmt.Println(arr[1])
fmt.Println(arr[2])
fmt.Println(arr[3])
// 通过len()函数可以得到不定参的参数个数
fmt.Println("len =", len(arr))
for _, v := range arr {
fmt.Println(v)
}
}
func main() {
test1(1, 2, 3, 4)
}
- 不定参函数的嵌套使用
func test3(arr ...int) {
fmt.Println(arr)
}
func test2(arr ...int) {
// 注意当不定参数作为另一个不定参函数的实参进行参数传递时,要在参数名称后面加上...
test3(arr...)
}
func main() {
test2(1, 2, 3, 4, 5)
}
14.3 函数的返回值
定义函数的时候,在函数的括号前面会写函数的返回值,返回值书写有两种情况
- 不写返回值的名称,只写返回值的类型
func test() int {
return 10
}
- 返回值的类型和名称都写:直接给返回值的那个变量赋值就相当于做了返回值了,return时就可以不写return后面的变量名了,当然也可以写上
func test() (value int) {
value = 10
return
// return value
// 上面这两个return的写法都是正确的
}
- 当返回值有多个的时候
func test5() (a int, b int, c int) {
a = 10
b = 20
c = 30
return
}
func main() {
// 函数如果有多个返回值,必须全部接受,如果不全部接受的话会报错
// 接受的方式:使用 _ 占位符
a, b, _ := test5()
fmt.Println(a)
fmt.Println(b)
}
14.4 函数名
// 这个函数的函数名是一个存着函数在代码区的地址的一个常量
func demo(int) {
fmt.Println("hello world")
return
}
// 定义一个函数类型
type FUNCTYPE func(int)
func main() {
fmt.Println(demo)
// 用 FUNCTYPE 这个类型去定义一个变量
// 在定义的时候要注意FUNCTYPE的参数类型和个数要与赋值的函数的类型完全相同
var f FUNCTYPE = demo
fmt.Println(f)
// 既然f已经被赋值为demo的值,那么现在就可以用f进行函数的调用,使用方法和func完全相同
f(0)
fmt.Printf("%T\n", demo)
}
// 输出
0x2040
0x2040
hello world
func(int)
15. 作用域
如果想使用不同的包下的函数或者是变量,使用包名.函数名
或包名.变量名