这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
0 前言
Go是一门编译型语言,Go语言的工具链将源代码及其依赖转换成计算机的机器指令(译注:静态编译)。Go语言提供的工具都通过一个单独的命令go调用,go命令有一系列子命令。
1 基本语法一览
1.1 包和文件
go语言的包类似于java的package,cpp的#include。目的都是用于模块化,封装,单独编译,代码重用。每个包对应一个独立的名字空间,比如引入fmt,就要通过fmt.Sprinltf来访问里面的函数。包的命名通常与包的所在目录相同。
1.2 声明
Go语言主要有四种类型的声明语句:var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明
1.3 控制语句
同样,Go支持For,If,switch三个控制语句
值得注意的是
For支持range操作,也就是如果定义了一个数组nums,可以使用for i, num := range nums的方式遍历If不包含(),并且一定要执行语句加{}switch的每个case不想cpp,java一样要加break才可以防止执行下一个case。想要执行后面的case需要添加fallthrough
1.4 数据类型
数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。
// 一维
var a [5]int
// 二维
var twoD [2][3]int
// 如果在数组的长度位置出现的是“...”省略号,则表示数组的长度是根据初始化值的个数来计算。
q := [...]int{1, 2, 3}
// 修改不同索引下的数值,数组长度为100
r := [...]int{10: 1, 99: -1}
由于数组的僵化了长度信息,通常只会用在生成摘要,加密等特定大小的信息,一般使用slice代替数组
Slice
Slice(切片)表示可变长的序列,每个元素都有相同的类型。一个slice由三个部分构成:指针、长度和容量。
创建方式:
// 通过数组来定义切片
var array [5]int
slice1 := array[:] // 拷贝全部
// 使用make函数
slice1 := make([]int, 5)
// 直接初始化
slice1 :=[]int{1,2,3} // 和数组最大的不同在于[]没有数字
追加函数Append与扩容:
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
s = append(s, "d")
fmt.Println(s) // [a b c d]
slice的扩容采用2倍扩容的方式,当len=cap时,触发扩容
func main() {
var x, y []int
for i := 0; i < 10; i++ {
y = append(x, i)
fmt.Printf("%d cap=%d\t len=%d\t %v\n", i, cap(y), len(y), y)
x = y
}
}
// 输出
/*
0 cap=1 len=1 [0]
1 cap=2 len=2 [0 1]
2 cap=4 len=3 [0 1 2]
3 cap=4 len=4 [0 1 2 3]
4 cap=8 len=5 [0 1 2 3 4]
5 cap=8 len=6 [0 1 2 3 4 5]
6 cap=8 len=7 [0 1 2 3 4 5 6]
7 cap=8 len=8 [0 1 2 3 4 5 6 7]
8 cap=16 len=9 [0 1 2 3 4 5 6 7 8]
9 cap=16 len=10 [0 1 2 3 4 5 6 7 8 9]
*/
Map
无序的key/value对的集合。写为map[K]V,K必须支持==运算,如前面的slice就不能作为key,因为其不支持==计算。
创建方式:
ages := make(map[string]int)
ages["w1nd"] = 2
ages["alice"] = 3
删除方式:
delete(ages, "alice") // 如果没有该key也没事
注意事项:
- 不允许对map元素进行取址操作,因为会动态增长,可能导致每次地址都不一样
- map迭代顺序不确定,也就是使用
for...range遍历的顺序是随机的 - map自身也不能进行==比较
tips:虽然slice不能作为key,但可以通过一个辅助函数来进行转换
var m = make(map[string]int)
func k(list []string) string { return fmt.Sprintf("%q", list) }
func Add(list []string) { m[k(list)]++ }
func Count(list []string) int { return m[k(list)] }
结构体
由零个或多个任意类型的值聚合成的实体。
创建方式:
type user struct {
name string
password string
}
// 访问直接用.
var d user
d.name = "wang"
d.password = "1024"
// 结构体指针
var d1 *user
d1 = &d
注意事项:
- 结构体可以进行==比较
- 允许结构体嵌套
结构体方法
此方法一般比其他普通方法多一个接收器。如下
// 格式
func (recv receiver_type) methodName(parameter_list) (return_value_list) {
...
}
// 栗子
func (u *user) resetPassword(password string) { // 注意:在接收器是指针时,方法可以改变接收器的值
u.password = password
}
1.5 String
字符串,比较简单,列出几个常用API:
fmt.Println(strings.Contains(a, "ll")) // true,判断是否包含该字符串
fmt.Println(strings.Count(a, "l")) // 2,返回该字符的数量
fmt.Println(strings.HasPrefix(a, "he")) // true,是否是该前缀
fmt.Println(strings.HasSuffix(a, "llo")) // true,是否是该后缀
fmt.Println(strings.Index(a, "ll")) // 2,下标
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo,拼接
fmt.Println(strings.Repeat(a, 2)) // hellohello,重复
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo,替换
fmt.Println(strings.Split("a-b-c", "-")) // [a b c],拆分
fmt.Println(strings.ToLower(a)) // hello,小写
fmt.Println(strings.ToUpper(a)) // HELLO,大写
2 常用库
2.1 fmt
输入输出标准库。
有以下API:
Print: 输出到控制台,不接受任何格式化操作
Println: 输出到控制台并换行
Printf : 只可以打印出格式化的字符串。只可以直接输出字符串类型的变量(不可以输出别的类型)
Sprintf:格式化并返回一个字符串而不带任何输出
Fprintf:来格式化并输出到 io.Writers 而不是 os.Stdout
占位符
%v 值的默认格式。
%+v 类似%v,但输出结构体时会添加字段名
%#v 相应值的Go语法表示
%T 相应值的类型的Go语法表示
%% 百分号,字面上的%,非占位符含义
2.2 json
json解析库。
func Marshal(v interface{}) ([]byte, error) // 序列化,一个是序列化对象
func Unmarshal(data []byte, v interface{}) // 反序列化,一个是需要被序列化的对象,另一个是表示这个对象的类型。
2.3 time
go的时间库,有如下API:
now := time.Now()
// *时间类型*
fmt.Printf("当前时间是:%s\n", now.String())
fmt.Printf("%d年", now.Year())
fmt.Printf("%d月", now.Month())
...
// *时间戳*
timestamp1 := now.Unix() //时间戳
timestamp2 := now.UnixNano() //纳秒时间戳
// *时间间隔*
now := time.Now() //获取当前时间
// 时间间隔4000秒
endTime := now.Add(time.Second * 4000)
// 计算时间间隔
Duration := time.Unix(0, endTime.Sub(now).Nanoseconds())
// *定时器*
tick := time.Tick(time.Second) // 倒计时1s
2.4 strconv
实现了基本数据类型与其字符串表示的转换。有如下API
// 将字符串类型的整数转换为int类型
func Atoi(s string) (i int, err error)
// 将int类型数据转换为对应的字符串表示
func Itoa(i int) string
// 返回字符串表示的整数值,接受正负号。
func ParseInt(s string, base int, bitSize int) (i int64, err error)
// 解析一个表示浮点数的字符串并返回其值。
func ParseFloat(s string, bitSize int) (f float64, err error)
。。。
2.5 env
通过os包来获取环境变量
// go run example/20-env/main.go a b c d
fmt.Println(os.Args) // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1 localhost
3 总结
本次课程主要学习GO的基本语法以及常用库,本文只是简单总结了下,并且课程也有讲了三个实战小项目,由于涉及内容过多,这里就不阐述了。