入门
Go 运行环境
- GOROOT: Go 的安装路径
- GOPATH: 当前用户 HOME 目录/go ~/go $HOME/go,目前第三方包安装目录,第三方包如果 install 就要编译可执行文件,就放在 bin 目录中
- PATH: 增加了~/go/bin 目录,等价于 GOPATH + bin,bin(binary)二进制,go 可执行文件所在目录
命名方式
go 变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则:
- 首字符可以是任意 Unicode 字符或下划线
- 首字符以外可以是任意 Unicode 字符、下划线或数字
- 名字的长度无限制
命名规范
- 标识符采用 CamelCase 驼峰命名法
- 如果只在包内可用,就采用小驼峰命名
- 如果要在包外可见,就采用大驼峰命名
- 简单循环变量可以使用 i、j、k、v 等
- 条件变量、循环变量可以是单个字母或单个单词,Go 倾向于使用单个字母,Go 建议使用更短小
- 常量驼峰命名即可
- 在其它语言中,常量多使用全大写加下划线的命名方式,Go 语言没有这个要求
- 对约定俗成的全大写,例如 PI
- 函数/方法的参数,返回值应是单个单词或者单个字母
- 函数可以是多个单词命名
- 类型可以是多个单词命名
- 方法由于调用时会绑定类型,所以可以考虑使用单个单词
- 包以小写单词命名,包名应该和导入路径的最后一段路径保持一致
- 接口优先采用单个单词命名,一般加 er 后缀,Go 语言推荐尽量定义小接口,接口也可以组合
关键字
关键字 | - | - | - | - |
---|---|---|---|---|
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | if | range | type | continue |
for | import | return | fallthrough | var |
保留字
常量 | 数据类型 | - | - | - | 函数 | - | - |
---|---|---|---|---|---|---|---|
true | int | uint | uintptr | bool | make | copy | imag |
false | int8 | uint8 | float32 | byte | len | close | panic |
iota | int16 | uint16 | float64 | rune | cap | delete | recover |
nil | int32 | uint32 | complex128 | string | new | complex | - |
- | int64 | uint64 | complex64 | error | append | real | - |
算数运算符
运算符 | 描述 | 运算符 | 描述 | 运算符 | 描述 | 运算符 | 描述 | 运算符 | 描述 |
---|---|---|---|---|---|---|---|---|---|
+ | 相加 | - | 相减 | * | 相乘 | / | 相除 | % | 求余 |
关系运算符
运算符 | 描述 |
---|---|
== | 检查两个值是否相等,如果相等就返回 true,否则返回 false |
!= | 检查两个值是否不相等,如果不相等就返回 true,否则返回 false |
> | 检查左边值是否大于右边值,如果是返回 true,否则返回 false |
>= | 检查左边值是否大于等于右边值,如果是返回 true,否则返回 false |
< | 检查左边值是否小于右边值,如果是返回 true,否则返回 false |
<= | 检查左边值是否小于等于右边值,如果是返回 true,否则返回 false |
逻辑运算符
运算符 | 描述 |
---|---|
&& | 逻辑 AND 运算符:如果两边的操作数都是 true,则为 true,否则为 false |
|| | 逻辑 OR 运算符:如果两边的操作数有一个为 true,则为 true,否则为 flase |
! | 逻辑 NOT 运算符:如果条件为 true,则为 false,否则为 true |
位运算符(比较二进制位数)
运算符 | 描述 |
---|---|
& | 参与运算的两位数各对应的二进位相与(两位均为 1 才为 1) |
| | 参与运算的两位数各对应的二进位相或(两位有一个为 1 就为 1) |
^ | 参与运算的两位数各对应的二进位相异或,当两对应的二进位相异时,结果为 1(两位不一样则为 1)。作为一元运算符时表示按位取反,符号位也跟着变。 |
<< | 左移 n 位就是乘以 2 的 n 次方。a<<b 是把 a 的各二进位全部左移 b 个位置 |
>> | 右移 n 位就是除以 2 的 n 次方。a>>b 是把 a 的各二进位全部右移 b 个位置 |
补码
- | 二进位 | 十进位值 |
---|---|---|
源码 | 0 1 0 1 | 5 |
按位取反 | 1 0 1 0 | - |
末位加 1 | 1 0 1 1 | -5 |
位运算
- | & | | | ^ |
---|---|---|---|
操作数 1 | 0 1 0 1 | 0 1 0 1 | 0 1 0 1 |
操作数 2 | 0 1 1 0 | 0 1 1 0 | 0 1 1 0 |
结果 | 0 1 0 0 | 0 1 1 1 | 0 0 1 1 |
异或运算:^1 1 1 0 = 1 0 0 1,除了最高位符号位不变以外,其它都从 0 变 1 或者 1 变 0
go
// %b代表二进制,%d代表十进制
func bitOp() {
//获取系统架构和系统位数
fmt.Printf("os arch %s,int size %d\n", runtime.GOARCH, strconv.IntSize)
//260=2^8+2^2=100000100
fmt.Printf("260 %b\n", 260)
//二进制:110&101=100,十进制:4
fmt.Printf("二进制:%b,十进制%d\n", 6&5, 6&5)
//二进制:110&101=111,十进制:7
fmt.Printf("二进制:%b,十进制%d\n", 6|5, 6|5)
//二进制:110&101=011,十进制:3
fmt.Printf("二进制:%b,十进制%d\n", 6^5, 6^5)
//二进制:101>>2=001,十进制:1
fmt.Printf("二进制:%b,十进制%d\n", 5>>2, 5>>2)
//二进制:101<<2=10100,十进制:20
fmt.Printf("二进制:%b,十进制%d\n", 5<<2, 5<<2)
}
func main() {
bitOp()
}
- | 原运算符 | 操作 | 运算后 | 备注 |
---|---|---|---|---|
正数右移 | 0 1 0 1 | >>2 | 0 0 0 1 | 高位补 0 |
正数左移 | 0 1 0 1 | <<2 | 0 1 0 0 | 低位补 0 |
负数右移 | 1 1 0 1 | >>2 | 1 1 1 1 | 高位补 1 |
负数左移 | 1 1 0 1 | <<2 | 0 1 0 0 | 低位补 0,负数左移后不一定为负数 |
赋值运算符
运算符 | 描述 | 运算符 | 描述 |
---|---|---|---|
= | 将右值赋值给左值 | <<= | 左移后赋值 |
+= | 相加后再赋值 | >>= | 右移后赋值 |
-= | 相减后再赋值 | &= | 按位与后赋值 |
*= | 相乘后再赋值 | |= | 按位或后赋值 |
/= | 相除后再赋值 | ^= | 按位异或后赋值 |
%= | 求余后再赋值 | - | - |
变量类型
类型 | go 变量类型 | fmt 输出 |
---|---|---|
整形 | int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 | %d |
浮点型 | float32 float64 | %f %e %g |
复数 | complex128 complex64 | %v |
布尔型 | bool | %t |
指针 | uintptr | %d %p |
引用 | map slice channel | %v |
字节 | byte | %d |
任意字符 | rune | %d |
字符串 | string | %s |
错误 | error | %v |
检测数据类型 | %V |
变量初始化
- 如果声明后未显式初始化,数值型初始化 0,字符串初始化为空字符串,布尔型初始化为 false,引用类型、函数、指针、接口初始化为 nil
go
var a string='America'
var a,b int=3,7
var a="America"//类型推断
var a,b="America",7//类型推断
- 函数内部的变量(非全局变量)可以通过:=声明并初始化
go
a:=3
- 下划线表示匿名变量,匿名变量不占命名空间,不会分配内存,因此可以重复使用
go
_=2+4
常量
- 常量在定义时必须赋值,且程序运行期间其值不能改变(命名建议大写)
- Go 里面常量不能为数组,
,这样是不被允许的,因为数组的容器内容会变化,不能在编译期明确得确定下来.const a = [2]int{1,2}
go
const PI float32=3.1415926
const(
PI=3.1415926
E=2.71
)//可以这样子定义常量
const(
a=100
b //100,跟上一行的值相同
c //100,跟上一行的值相同
)
iota
- iota 定义成批常量,iota 从 0 开始,从成批的第一行开始
go
const(
a = iota //0
b //1
c //2
d //3
)
const(
a = iota //0
b //1
_ //2
d //3
)
const(
a = iota //0,iota = 0
b = 30 //30 ,iota = 1
c = iota //2,假如c不赋值iota,那么c=30,和上一行相同
d //3
)
const (
m = 100 // 100 ,iota = 0
n // 100, iota = 1
a = iota * 2 //2 * 2 = 4
b // 3 * 2 = 6
c // 4 * 2 = 8
d // 5 * 2 = 10
)
const(
_ = iota //iota=0
KB = 1<< (10*iota) //iota=1
MB= 1 << (10*iota) //iota=2
GB= 1 << (10*iota) //iota=3
TB= 1 << (10*iota) //iota=4
)
const(
a,b = iota + 1,iota + 2 //1,2 iota=0,0+1,0+2
c,d //2,3 iota=1,1+1,1+2
e,f //3,4 iota=2,2+1,2+2
)
字面量
- 字面量:没有出现变量名,直接出现了值。基础类型的字面量相当于常量。
go
fmt.Printf("%t\n",04 == 4.00) //用到了整型字面量和浮点型字面量
fmt.Printf("%v\n",.4i) //虚数字面量0.4i
fmt.Printf("%t\n",'\u4f17' == '众') //Unicode和rune字面量比较
fmt.Printf("Hello\nWorld\n!\n") //字符串字面量
变量作用域
- 全局变量,大写字母开头,所有地方都可以访问,跨 package 访问时需要带上 package 名称
- 全局变量,小写字母开头,仅本 package 内都可以访问
- 局部变量,仅本函数内可以访问,内部声明的变量可以跟外部声明的变量有冲突,以内部的优先级更高,内部对 b 的修改不影响外部的 b 的值
- 仅函数内部可以使用:=快速定义变量,全局定义变量必须使用 var/const 定义。
- 一个 package(文件夹)下,包名可以和 package(文件夹) 名称不一样,但是文件夹下面的文件设定的包名必须命名一致
go
var(
A=3 //全局变量,大写字母开头
b=4 //全局变量,小写字母开头
)
func foo(){
b:=5 //局部变量,仅本函数内可以访问
{
b:=6 //仅{}圈定的作用域内可以访问
}
}
注释的形式
- 单行注释,以//打头
- 多行注释,连续多行以//打头,或者在段前使用/*,段尾使用*/
- 多行注释之间不能出现空行
- NOTE:引人注意,TODO:将来需要优化,Deprecated:变量或函数强烈建议不要再使用
- 注释行前加缩进即可写 go 代码
注释的位置
- 包注释: 在 package xxx 的上方,一个包只需要在一个地方写包注释,通常会专门写一个 doc.go,里面只有一行 package xxx 和关于包的注释。
- 结构体注释: 在 type xxx struct 上方
- 函数注释: 在 func xxx()上方
- 行注释: 在行上方或右侧
运行go doc 包名
后,控制台会输出包的注释,以及包内的以大写首写命名的全局变量及函数
godoc
- godoc 可以为项目代码导出网页版的注释文档
- 需要先安装 go install golang.org/x/tools/cmd/godoc@latest
- 终端输入启动文档: godoc -http=:6060
- 用浏览器访问:localhost:6060