一、简介
- Go(又称Golang)是Google开发的一种静态、强类型、编译型、并发型,并具有垃圾回收功能的编程语言
二、变量 & 常量
2.1 变量
- 声明
var name type
- 变量声明后,会自动初始化
int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil
- 命名规则遵循骆驼命名法
var a, b int
var p *int
var f int = 99
//批量
var (
c int
d string
)
//简写
s := "string"
x, y := 1.0, 2.0
//值交换
x, y = y, x
fmt.Println(a, b, f, c, d, p, s, x, y) //0 0 99 0 <nil> string 2 1
- 匿名变量
func getPoint() (int, int) {
return 100, 200
}
xPoint, _ := getPoint()
_, yPoint := getPoint()
fmt.Println(xPoint, yPoint)
2.2 常量
-
const
关键字 - 只能是布尔型、数字型(整数型、浮点型和复数)和字符串型
- 定义常量的表达式必须为能被编译器求值的常量表达式
- 声明,类型可选
const name [type] = value
- iota
三、基本数据类型
3.1 布尔型
- 关键字
bool
- 值仅有
true
orfalse
- 默认值
false
- 存在短路行为,既如果运算符左边的值可以确定整个布尔表达式的结果,则运算符右边不再执行(同其他语言)
3.2 字符串
- 关键字
string
- 默认值为空
- 值为任意数据的不可变字节序列
- UTF-8 字符占位(ASCII上的字符占一个字节,其他占两个字节)
- 转义字符
\n
换行符
\r
回车符
\t
tab 键
\u 或 \U
Unicode 字符
\\
反斜杠自身 - 比较运算符(==、!=、<、<=、>=、>)
- 获取大小
len()
- 字符串操作,借助于
strings
包
str1 := "!"
//拼接
str := "Hello world" + str1
//索引
fmt.Println(str[0]) //72
//截取(取前不取后)
fmt.Println(str[0:4]) //hell
//是否包含
fmt.Println(strings.Contains(str, "hello")) //true
fmt.Println(strings.Contains(str, "h & k")) //false
//是否包含多个
fmt.Println(strings.ContainsAny(str, "h & k")) //true
//是否以子串开始
fmt.Println(strings.HasPrefix(str, "hello")) //true
//是否以子串结束
fmt.Println(strings.HasSuffix(str, "!")) //true
//大小写
fmt.Println(strings.ToLower(str)) //hello world!
fmt.Println(strings.ToUpper(str)) //HELLO WORLD!
//获取索引,查找不到返回-1
fmt.Println(strings.Index(str, "l")) //2
fmt.Println(strings.LastIndex(str, "l")) //9
//匹配多个字节组成的字符
fmt.Println(strings.IndexRune("城市花园", '花')) //6
//切片
fmt.Println(strings.Split(str, " ")) //[Hello world!]
//组合(元素类型为string)
fmt.Println(strings.Join(strings.Split(str, " "), " ")) //Hello world!
fmt.Println(strings.Join([]string{"a", "b", "c"}, ", ")) //a, b, c
//替换(参数:源字符串,需要替换, 新字符串, 匹配前n个记录)
fmt.Println(strings.Replace(str, "world", "Jony", 1)) //Hello Jony!
- 多行时必须使用反引号
`
,既字符串字面量
var s string = `First line
hello
end line
`
- 类型转换,
strconv
包
num, _ := strconv.Atoi("10")
fmt.Println(num-1) //9
3.3 数值类型
整数
- 有符号
int、int8、int16、int32、int64 - 无符号
uint、uint8、uint16、uint32、uint64、uintptr
注:int和uint会因编译器和计算机硬件,大小会在 32bit 或 64bit 之间变化
浮点数
- float32 EEE-754 32位浮点型数
- float64 IEEE-754 64位浮点型数
复数
- complex64 32 位实数和虚数
- complex128 64 位实数和虚数
四、派生类型
4.1 指针(pointer)
- 声明
var var_name *var-type
- 取地址操作符
&
- 指针变量取指向地址保存数据操作符
*
-
fmt.Printf
打印内存地址%f
- 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算
data := "pointer data"
ptr := &data
fmt.Printf("%p\n", &data) //0xc00008a040
fmt.Println(ptr) //0xc0000681e0
fmt.Println(*ptr) //pointer data
str := new(string)
*str = "string data"
fmt.Printf("%p\n", str) //0xc000098050
fmt.Printf("%s\n", *str) //string data
//空指针取值会报错
var nullPointer *string
if(nullPointer == nil) {
fmt.Println(nullPointer) //<nil>
}
4.2 数组
- 声明
var 数组变量名 [元素数量]Type
- 定长特定类型的元素序列
var intArr [3]int
var arr1 [3]int = [3]int{1, 2}
arr2 := [...]int{1, 2, 0}
arr3 := [2]int{1, 2}
fmt.Println(intArr) //[0 0 0]
fmt.Println(arr1) //[1 2 0]
fmt.Println(arr2) //[1 2 0]
fmt.Println(arr1 == arr2) //true
// fmt.Println(arr1 == arr3) //error
//数组遍历
for k, v := range arr3 {
fmt.Println(k, v)
}
//多维数组
var multArr [2][3]int
//此种方式初始化一行的元素可以省略自动使用默认值,但不能省略一行否则报错
multArr = [2][3]int{{1, 2, 3}, {4, 5}} //[[1 2 3] [4 5 0]]
fmt.Println(multArr)
multArr1 := [4][3]int{1:{1, 1, 1}, 3:{3, 3, 3}}
fmt.Println(multArr1) //[[0 0 0] [1 1 1] [0 0 0] [3 3 3]]
fmt.Println(multArr1[3]) //[3 3 3]
multArr1[2][1] = 99
fmt.Println(multArr1) //[[0 0 0] [1 1 1] [0 99 0] [3 3 3]]
4.3 切片
- 切片(slice)是对数组的一个连续片段(整个数组,由起始和终止索引标识的一些项的子集)的引用(对数组的抽象)
- 切片结构包含地址、大小和容量
- 大小不固定
- 声明
var name []Type
//从数组中生成切片
arr := [...]int{1, 2, 3, 4, 5}
fmt.Println(arr) //[1 2 3 4 5]
fmt.Println(arr[0:0]) //[]
fmt.Println(arr[:]) //[1 2 3 4 5]
fmt.Println(arr[2:]) //[3 4 5]
fmt.Println(arr[:2]) //[1 2]
fmt.Println(arr[1:3]) //[2 3]
//声明切片
var strSlice []string
var intSlice []int
var emptySlice = []int{} //分配到了内存,但无元素
fmt.Printf("%p, %p, %p\n", strSlice, intSlice, emptySlice) //0x0, 0x0, 0x1195ab8
fmt.Println(strSlice, intSlice, emptySlice) //[] [] []
fmt.Println(strSlice == nil) //true
fmt.Println(emptySlice == nil) //false
//append()函数添加元素,返回一个切片
fmt.Println(append(intSlice, 1)) //[1]
fmt.Println(append(intSlice, 1, 2)) //[1 2]
//追加的为切片时需解包
fmt.Println(append(intSlice, []int{1, 2, 3}...)) //[1 2 3]
//使用 make() 内建函数,动态地创建一个切片
s1 := make([]int, 2)
s2 := make([]int, 2, 6)
fmt.Println(s1, s2) //[0 0] [0 0]
//copy
slice1 := []int{1, 1, 1}
slice2 := []int{2, 2, 2, 2, 2}
copySlice1 := make([]int, 5)
copySlice2 := make([]int, 3)
copy(copySlice1, slice1)
copy(copySlice2, slice2)
fmt.Println(copySlice1) //[1 1 1 0 0]
fmt.Println(copySlice2) //[2 2 2]
4.4 Map
- 声明
var mapname map[keytype]valuetype
make
声明可选标明大小make(map[keytype]valuetype, cap)
- 仅只读线程安全
var emptyMap map[string]int
emptyMap1 := make(map[string]int, 10)
fmt.Println(emptyMap, emptyMap1) //map[] map[]
mapList := map[string]int{"key1":1, "key2":2}
fmt.Println(mapList, len(mapList)) //map[key1:1 key2:2] 2
mapList["key3"] = 3
for key, value := range mapList {
fmt.Println(key, value)
}
//删除
delete(mapList, "key2")
fmt.Println(mapList) //map[key1:1 key3:3]
value 值
- 实测为
Map
或者切片
时正确,为数组时报错
type Rcus struct {
Id bson.ObjectId
RoomNum string
AirconMap map[string][]int
DmMap map[string]int
}
rcu := new(models.Rcus) //已经初始化各个成员
// rcu := &(models.Rcus)
rcu.Id = bson.NewObjectId()
rcu.RoomNum = "1204"
//正确
// ariconMap := make(map[string][]int)
// aircon1 := []int{1, 2, 3, 4}
// ariconMap["AC1"] = aircon1
// ariconMap["AC2"] = []int{1, 2, 3, 4}
// rcu.AirconMap = ariconMap
//正确
// aircon := []int{1, 2, 3, 4}
// rcu.AirconMap = map[string][]int{"ac":aircon}
rcu.DmMap = map[string]int{"1":1}
fmt.Println(rcu)
sync.Map
- 优于加锁解决map线程安全,sync 包下的特殊结构
- 无须初始化,直接声明即可
//sync package
var syncMap sync.Map
//存储
syncMap.Store("key1", 1)
syncMap.Store("key2", 2)
syncMap.Store("key3", 3)
//获取值
fmt.Println(syncMap.Load("key2")) //2 true
//删除
syncMap.Delete("key3")
//遍历
syncMap.Range(func(k, v interface{}) bool {
fmt.Println(k, v)
return true //true 继续,false 结束
})
其他:函数、Channel、接口、结构体
四、常用标准库
包名 | 功能 |
---|---|
bufio | 带缓冲的 I/O 操作 |
bytes | 实现字节操作 |
container | 封装堆、列表和环形列表等容器 |
crypto | 加密算法 |
database | 数据库驱动和接口 |
debug | 各种调试文件格式访问及调试功能 |
encoding | 常见算法如 JSON、XML、Base64 等 |
flag | 命令行解析 |
fmt | 格式化操作 |
go | Go语言的词法、语法树、类型等。可通过这个包进行代码信息提取和修改 |
html | HTML 转义及模板系统 |
image | 常见图形格式的访问及生成 |
io | 实现 I/O 原始访问接口及访问封装 |
math | 数学库 |
net | 网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等 |
os | 操作系统平台不依赖平台操作封装 |
path | 兼容各操作系统的路径操作实用函数 |
plugin | Go 1.7 加入的插件系统。支持将代码编译为插件,按需加载 |
reflect | 语言反射支持。可以动态获得代码中的类型信息,获取和修改变量的值 |
regexp | 正则表达式封装 |
runtime | 运行时接口 |
sort | 排序接口 |
strings | 字符串转换、解析及实用函数 |
time | 时间接口 |
text | 文本模板及 Token 词法器 |