这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天,
一、本堂课重点内容:
- go语言基础语法
二、详细知识点介绍:
变量
go语言是一门强类型语言,每一个变量都有它自己的变量类型。
常见类型
字符串(string),整数(int),浮点型(float),布尔(bool)型等
变量声明
go语言变量的声明有两种方式。
- 通过
var 变量名 变量类型的形式来声明变量 - 通过
变量名 := 初始值的形式来声明变量,此时一定要进行初始化,go会通过初始值来推断变量类型,如果有需要也可以写出变量类型
if else
go语言里面的if else写法和C或者C++类似。但有两点不同之处。
- if后面不需要加括号。
if(条件)是错的,if 条件即可 - if后面必须接大括号。c/c++里if后面可以直接接上一个语句,但在go里是不行的,必须接上大括号
循环
不同于c/c++,go里面只有for循环,没有while循环。
for循环有以下三种常用写法
for {}代表死循环,与c/c++的while(true){}相同for 单次表达式;条件表达式;末尾循环体 {}这与c/c++类似,例如for i:=1; i <= 100; i++ {}for 条件表达式 {}其实是2省略了单次表达式和末尾循环体,与c/c++的while(条件表达式) {}相同
switch
结构与c/c++的类似,但有以下不同之处
- 在go里面,switch case只会执行对应的case,然后就会退出switch,但是在c/c++里不加上case会继续往下执行程序
- 在go里面,switch case的case类型可以使用任意类型,但在c/c++,它只能是整数
- go可以在switch后面不加任何的变量,然后在case里面写条件分支,这可以用来代替if-else,并且逻辑更为清晰
数组
数组就是一个具有编号且长度固定的元素序列。
定义一个数组可以用var 变量名 [数组大小]变量类型
切片
- 切片不同于数组可以任意更改长度,然后也有更多丰富的操作。
- 使用make来创建切片,格式为
slice1 := make([]类型),也可以直接指定长度。 - 切片可以用append来追加元素,例如
s = append(s, 'd')。 - 切片实际上是一个存储了长度、容量,以及指向一个数组的指针的结构体。
- 切片拥有像python一样的切片操作,例如
s[2:5]是取出s的第3-5(下标为2-4)的元素。但是不支持负数索引
map
map即为哈希表。
- 使用make来创建一个空map,
m := make(map[key]val),其中key为map 的键值,val为存储的值类型 - 使用delete来删除map中的键值对,
delete(map, key),其中map为具体变量,key为所对应key值类型 - go的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序
range
对于一个切片或者是map来说,可以用range来遍历它们,这样代码更为简洁。
- range遍历的时候,对于数组会返回两个值,第一个是索引,第二个是对应位置的值,不需要索引时可以用
_来忽略。
函数
go中函数的定义格式为func 函数名(变量名1 变量类型1, ...) 返回类型 {}。例如
func add(a int, b int) int {
return a+b
}
即为一个两个变量相加的函数。
- go里面的函数原生支持返回多个值
- 在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息。
结构体
go中结构体的定义为
type 结构体名 struct {
变量名1 类型1
变量名2 类型2
...
}
type user struct {
name string
password string
}
结构体构造时需要传入字段的初始值,可以用这种键值对的方式去指定初始值。
a := user{name:"wang",password:"1024"}
b := user{"wang","1024"}
c := user{name:"wang"}
结构体方法
go里面的结构体方法类似于其他语言里的类成员函数。
具体的格式在基础函数格式的函数名前加上括号,里面填入结构体,例如
func (u user) checkPassword(password string) bool {
return u.password == password
}
错误处理
go习惯使用一个单独的返回值来传递错误信息。
不同于java自家家使用的异常。go语言的处理方式,能够很清晰地知道哪个函数返回了错误,并且能用简单的if else来处理错误。
在函数里面,我们可以在那个函数的返回值类型里面,后面加一个error,就代表这个函数可能会返回错误。
字符串操作与字符串格式化
go的标准库strings包里面有很多常用的字符串工具函数。
a := "hello"
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
fmt.Println(len(a)) // 5
go的标准库的fmt包,里面有很多的字符串格式相关的方法。例如fmt.Printf便是类似于c/c++的printf。
此外在go中可以使用%v来打印任意类型变量,%+v打印详细的结果,%#v打印更详细的结果。
ype point struct {
x, y int
}
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p) // {1 2}
fmt.Printf("s=%v\n", s) // s=hello
fmt.Printf("n=%v\n", n) // n=123
fmt.Printf("p=%v\n", p) // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
JSON处理
go语言里面的JSON操作非常简单,对于一个已有的结构体,我们可以什么都不做,只要保证每个字段的第一个字母是大写,也就是是公开字段。那么这个结构体就能用json.Marshaler去序列化,变成一个JSON的字符串。
序列化之后的字符串也能够用json.Unmarshaler去反序列化。
默认序列化出来的字符串的话,它的风格是大写字母开头,而不是下划线。我们可以在后面用json tag等语法来去修改输出JSON结果里面的字段名。
时间处理
- 使用time.Now获取当前时间
- 使用time.Date构造一个带时区的时间
- 使用Sub求取两个时间的差,即时间段,再用Year、Month、Day、Hour等函数去获取时间段对应单位的数量
- 使用time.Unix获取时间戳
数字解析
使用strconv这个包进行字符串和数字之间的转换。
常见有Atoi和Itoa两个函数。
进程信息
- 使用os.Argv来获取程序启动时的命令行参数
- 使用os.Getenv和os.Setenv来获取环境变量和设置环境变量
杂项
- go的字符串可以通过"+"来连接,与py,java类似
- go能够直接去打印一个数组、map、结构体等
三、实践练习例子:
猜字谜游戏
大体上是使用当前时间作为种子生成一个小于100随机数作为最终答案,不断获取用户输入并反馈用户输入与最终答案的大小关系,直至用户猜到最终答案。
涉及到的知识点有时间处理、错误处理、字符串操作与格式化,循环结构与分支结构等。
在线字典
利用彩云翻译的api,通过go的JSON处理和http请求以及命令行参数,获取到传入参数的英文单词的一些信息。
涉及到的知识点有切片,字符串处理与格式化、JSON处理、进程信息等。
四、课后个人总结:
在在线字典里使用了两个网站来快速生成代码。
一个是Convert curl to Go用来生成等效curl命令行的go代码,一个是Json2go用来生成等效JSON文件的go结构体。
这两者自己实现的话要花费大量时间精力,恰恰说明了在实际开发过程中,运用合适的工具可以大大减少开发周期,提升开发效率。