01 关键字与标识符
标识符
标识符的作用
- 标识符是用来标识go中的变量名或函数名的
标识符的命名规范
规范
- 以字母或者_开头,后面跟着字母、数字、_
合法标识符举例
- a_b
- _a
- ab_23d
非法标识符举例
- 1ab 以数字开头
- case go里面的关键字
- a+b 带了运算符
空白标识符
- _ 本身就是一个特殊的标识符,被称为空白标识符
- 用来导入包,只初始化init函数,不使用内部方法
- 函数返回值不使用变量,多变量返回
25个关键字
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
36个 预定义标识符
- 基本类型的名称
- 一些基本的内置函数
append bool byte cap close complex complex64 complex128 uint16
copy false float32 float64 imag int int8 int16 uint32
int32 int64 iota len make new nil panic uint64
print println real recover string true uint uint8 uintptr
02 操作符
算术运算符
-
-
-
- / % ++ --
-
-
- 代码如下
package main
import "fmt"
func main() {
var a = 21
var b = 10
var c int
fmt.Printf("[初始化的值是什么: a=%d b=%d c=%d]\n", a, b, c)
// 加法
c = a + b
fmt.Printf("[加法操作: a+b=%d]\n", c)
// 减法
c = a - b
fmt.Printf("[减法操作: a-b=%d]\n", c)
// 乘法
c = a * b
fmt.Printf("[乘法操作: a*b=%d]\n", c)
// 减法
c = a / b
fmt.Printf("[除法操作: a/b=%d]\n", c)
// 取余
c = a % b
fmt.Printf("[减法操作: a对b取余=%d]\n", c)
// 自增
c++
fmt.Printf("[c自增: c++=%d]\n", c)
// 自减
c--
fmt.Printf("[c自减: c++=%d]\n", c)
/*
[初始化的值是什么: a=21 b=10 c=0]
[加法操作: a+b=31]
[减法操作: a-b=11]
[乘法操作: a*b=210]
[除法操作: a/b=2]
[减法操作: a对b取余=1]
[c自增: c++=2]
[c自减: c++=1]
*/
}
关系运算符
> < == !=
package main
import "fmt"
func main() {
var a = 10
var b = 5
if a > b {
fmt.Printf("a>b")
}
}
逻辑运算符
- && 逻辑 AND 运算符
- || 逻辑 OR 运算符
- ! 逻辑 NOT 运算符
package main
import "fmt"
func main() {
var a = true
var b = false
if a && b {
fmt.Printf("[ab 同为true才为true]\n")
}
if a || b {
fmt.Printf("[a b 中有一个为true 就是true]\n")
}
if !(a && b) {
fmt.Printf("[a b同为true再取非为true]\n")
}
}
位运算符
- 与操作 & 二进制位同为1 结果为1
- 或操作 | 二进制位至少一个为1 结果为1
- 异或操作 ^ 二进制位不同时 结果为1
- 左移运算符 << 左移n位就是乘以2的n次方
- 右移运算符 >> 右移n位就是除以2的n次方
package main
import "fmt"
func main() {
var a uint = 60
var b uint = 13
var c uint = 0
fmt.Printf("[a=%d 二进制=%08b]\n", a, a)
fmt.Printf("[b=%d 二进制=%08b]\n", b, b)
c = a & b
fmt.Printf("[与操作][%d=%d&%d][%08b=%08b & %08b ]\n", c, a, b, c, a, b)
c = a | b
fmt.Printf("[或操作][%d=%d | %d][%08b=%08b | %08b ]\n", c, a, b, c, a, b)
c = a ^ b
fmt.Printf("[异或操作][%d=%d^%d][%08b=%08b ^ %08b ]\n", c, a, b, c, a, b)
c = a << b
fmt.Printf("[左移放大操作][%d=%d&%d][%08b=%08b & %08b ]\n", c, a, b, c, a, b)
c = a >> b
fmt.Printf("[右移动缩小操作][%d=%d&%d][%08b=%08b & %08b ]\n", c, a, b, c, a, b)
/*
[a=60 二进制=00111100]
[b=13 二进制=00001101]
[与操作][12=60&13][00001100=00111100 & 00001101 ]
[或操作][61=60 | 13][00111101=00111100 | 00001101 ]
[异或操作][49=60^13][00110001=00111100 ^ 00001101 ]
[左移放大操作][491520=60&13][1111000000000000000=00111100 & 00001101 ]
[右移动缩小操作][0=60&13][00000000=00111100 & 00001101 ]
*/
}
赋值运算符
+= -= *= ...
package main
import "fmt"
func main() {
var a = 21
var c int
c = a
fmt.Println(c, a)
c += a
fmt.Println(c, a)
c *= a
fmt.Println(c, a)
/*
21 21
42 21
882 21
*/
}
关于指针的运算符
- & 返回变量存储地址 可以使用%p去打印地址
-
- 指针变量
var a *int
- 用来定义变量,类型是指针的
- 可以对指针地址再赋值或取值
- 指针变量
package main
import "fmt"
func main() {
var a = 4
var ptr *int
fmt.Printf("[a 变量类型为 %T]\n", a)
fmt.Printf("[ptr 变量类型为 %T]\n", ptr)
ptr = &a
fmt.Printf("[a 变量的值为 %d]\n", a)
fmt.Printf("[*ptr 的值为%d ]\n", *ptr)
fmt.Printf("[ptr 的值为%v ]\n", ptr)
fmt.Printf("[a 的指针地址为%p ]\n", &a)
/*
[a 变量类型为 int]
[ptr 变量类型为 *int]
[a 变量的值为 4]
[*ptr 的值为4 ]
[ptr 的值为0xc00001a098 ]
[a 的指针地址为0xc00001a098 ]
*/
}
03 变量、常量、枚举
变量
方法一:使用var 声明变量并初始化
- 关键字var可以使用结构类型声明变量,并初始化为零值,举例
var p int
- 关键字 var 创建了类型为 int 且名为 p 的变量,p被称作类型 int 的一个实例(instance)。
- 当声明变量时,这个变量对应的值总是会被初始化。
- 使用var关键字用零值初始化,对数值类型来说,零值是 0;对字符串来说,零值是空字符串;对布尔类型,零值是 false。
- 多变量声明
var a,b,c,d string
var 等号 :使用自定义数据初始化
var p int = 10
var特点:可以在函数外部使用,可以声明初始化全局变量
- 举例使用 var=XXXX 初始化全局缓存
方法二:使用短变量声明操作符(:=) 初始化
特点1:使用自定义值初始化
p:=10
特点2:不可以在函数外部使用,不可以声明初始化全局变量
- 可以试一试 .\compute.go:8:1: syntax error: non-declaration statement outside function body
常量 const定义的
- 定义在全局的位置,函数外部
- 常量必须赋值,否则报 Missing value in const declaration
const Pi = 3.1415
const Max float64 = 1000.11111
const cname = "go编程"
const dname
枚举
- go中没有enum这么一个关键字来定义,而是依靠const和iota
package main
import "fmt"
const (
a = iota
b
c
d
)
func main() {
fmt.Println(a, b, c, d)
}
- 自定义类型
package main
import "fmt"
type MyType int
const (
T1 MyType = iota
T2
T3
T4
)
func main() {
fmt.Println(T1, T2, T3, T4)
}
- _ 可以跳过值
package main
import "fmt"
type MyType int
const (
T1 MyType = iota
T2
_
_
T3
T4
)
func main() {
fmt.Println(T1, T2, T3, T4) //0 1 4 5
}
- 中间插值 iota 会被覆盖掉 不再继续自增。但是用另一个 iota 接一下,又会继续自增
package main
import "fmt"
type MyType int
const (
a = iota
b = 5
c
d = iota
e
)
func main() {
fmt.Println(a, b, c, d, e) //0 5 5 3 4
}
- 位掩码表达式
package main
import "fmt"
type MyType int
const (
T1 MyType = 1 << iota
T2
_
_
T3
T4
)
func main() {
fmt.Println(T1, T2, T3, T4) //1 2 16 32
}
- 定义数量级 ,比如说字节大小
package main
import "fmt"
type MyType int
const (
_ = iota
KB float64 = 1 << (10 * iota)
MB
GB
TB
)
func main() {
fmt.Println(KB, MB, GB, TB) //1024 1.048576e+06 1.073741824e+09 1.099511627776e+12
fmt.Println(1 << 10)
}
04 变量作用域
- 在 Golang 中,变量作用域分为 :本地局部变量、全局变量、参数变量
本地局部变量
- 在函数、if 、for等中定义的变量,
- 生效范围:定义在函数里面则在整个函数范围有效; 定义在语义块,则在整个语义块生效
package main
import "fmt"
func T1() string {
str1 := "函数T1中的字符串变量"
fmt.Println(str1)
return str1
}
func main() {
// .\compute.go:12:14: undefined: str1
// 试图引用在函数里面定义的变量
//fmt.Println(str1)
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 报错是这个.\compute.go:18:14: undefined: i
// 试图引用在for里面定义的变量
//fmt.Println(i)
if str := T1(); str == "" {
fmt.Println("[函数返回为空]")
}
//
// 报错是这个.\compute.go:26:14: undefined: str
// 试图引用在if里面定义的变量
//fmt.Println(str)
}