这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
前言
本人是Go语言初学者,对于go的知识理解程度有限,涵请指出问题谢谢。在学go之前,就听说go未来在web场景下会应用很广泛,是一门天生支持高并发的新语言。这次笔记主要是关于Go的语法基础知识的。
课程:走进Go语言基础语言&Go语言案例实战
一、本堂课重点内容:
1.Go的基础语法 2.数组、切片、map 3.结构体、结构体方法、指针、函数
二、详细知识点介绍:
2.1 Go语言特性
Go语言是一门强类型和静态类型的语言。
- 高性能、高并发
- 语法简单、学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
基础语法
package main(入口文件)
import "fmt" 调用fmt包(输入输出字符串、格式化字符串)
func main(){ (主函数) fmt.Println("HelloWorld") }
以上的代码会在控制台输出 HelloWorld。
个人认为,func main类似于C/CPP的int main和Java的public static void main还有rust的fn main,是我们程序执行的入口。从func main开始,函数和方法压入运行栈。
$ go run helloworld.go
通过在控制台键入以上语句,将helloworld.go文件进行编译链接最终生成可执行文件。
2.2 Go语言变量
在Go语言中,var声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。变量声明的一般语法如下:
var 变量名字 类型 = 表达式
其中“类型”或“= 表达式”两个部分可以省略其中的一个。如果省略的是类型信息,那么将根据初始化表达式来推导变量的类型信息。如果初始化表达式被省略,那么将用零值初始化该变量。 数值类型变量对应的零值是0,布尔类型变量对应的零值是false,字符串类型对应的零值是空字符串,接口或引用类型(包括slice、指针、map、chan和函数)变量对应的零值是nil。数组或结构体等聚合类型对应的零值是每个元素或字段都是对应该类型的零值。——《The Go Programming Language》
与其他语言一样,Go语言的变量在初始化时如果没有赋值,是有对应的初值的。
同时,go语言提供了简短变量声明。以“名字 := 表达式”形式声明变量,变量的类型则根据上下文自动推导。
i := 100 // an int
var boiling float64 = 100 // a float64
var names []string
var err error
var p Point
2.3 Go语言常量
将var变量声明语句替换为const则是创建一个常量。 例如:
const s string = "constant"
该语句声明了一个值为"constant"的字符串常量s。
2.4 Go条件语句
与C语言类似 Go 语言提供了以下几种条件判断语句:
| 语句 | 描述 |
|---|---|
| if 语句 | if 语句 由一个布尔表达式后紧跟一个或多个语句组成。 |
| if...else 语句 | if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。 |
| if 嵌套语句 | 你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。 |
| switch 语句 | switch 语句用于基于不同条件执行不同动作。 |
| select 语句 | select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。 |
注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
——菜鸟教程
个人认为,select语句主要跟channel通道进行配合。
package main
import "fmt"
func main() {
/* 定义局部变量 */
var a int = 10
/* 使用 if 语句判断布尔表达式 */
if a < 20 {
/* 如果条件为 true 则执行以下语句 */
fmt.Printf("a 小于 20\n" )
}
fmt.Printf("a 的值为 : %d\n", a)
}
以上代码执行结果为:
a 小于 20
a 的值为 : 10
可以看到,go语言中的if后面的条件语句是不加括号的,即便加了括号,也会编译时被编译器默认去掉。 其他条件语句的使用方式类似于上方代码示例包括switch。
switch var1 {
case val1:
...
case val2:
...
default:
...
}
2.5 循环语句
与C语言不同,go只提供了for循环语句。
func main() {
for true {
fmt.Printf("这是无限循环。\n");
}
}
这个for循环是一个死循环,同时我们也可以看到,for后面的条件语句也是不加括号的。
同时,Go也是支持在循环中使用break和continue的。
Go 语言的 for 循环有 3 种形式,只有其中的一种使用分号。
和 C 语言的 for 一样:
for init; condition; post { }
类似于 C 的 while 一样:
for condition { }
类似于 C 的 for(;;) 一样:
for { }
Go也为我们提供了类似Python常用的for range。
for key := range oldMap
2.6 数组与切片
根据课程描述,真实业务里面,很少使用数组,主要用的是切片。而Slice(切片),它是可以增长和收缩的动态序列,slice功能也更灵活。
Go语言中的数组是固定长度的,在声明时需要指定数组长度。例如:
var arr [5]int
这样就声明了一个长度为5的整型数组。
而切片(slice)是可变长度的,可以动态增加或删除元素。切片是对数组的一个引用,因此改变切片的内容会直接影响到原数组。例如:
s := []int{1, 2, 3}
这样就声明了一个切片。
切片还支持切片操作,例如:
s := []int{1, 2, 3, 4, 5}
fmt.Println(s[1:3]) // 输出 [2, 3]
这样就可以得到一个新切片了。
2.8 Map哈希表
跟其它语言一样,Go语言中的map类型是一种关联数组,也称为字典或哈希表。它允许将键映射到值。键和值都可以是任何类型,但键必须是可以用==进行比较的。
声明一个map类型变量,可以这样:
var m map[string]int
这样就声明了一个将字符串映射到整型的map变量。 也可以使用make()函数创建map:
m := make(map[string]int)
使用map类型的变量,可以这样赋值:
m["apple"] = 3
查询map类型的变量,可以这样:
value, exist := m["apple"]
如果存在value就是对应的值,exist是bool类型,如果存在就是true,如果不存在就是false.
还有一些其他操作也可以用来操作map类型,例如:
- len(m) 获取map中元素个数
- delete(m, key) 删除元素
- range关键字来遍历map中的元素
需要注意的是map类型是无序的,每次遍历map类型的元素顺序可能不同.
2.9结构体
Go语言中的结构体(struct)是一种自定义类型,用于将多个不同类型的数据放在一起。
声明结构体类型,可以这样:
type Person struct {
name string
age int
}
这样就定义了一个名为Person的结构体类型,包含了两个字段:name和age。
创建结构体变量,可以这样:
p := Person{"Jack", 18}
或者
p := Person{name: "Jack", age: 18}
访问结构体变量的字段,可以这样:
fmt.Println(p.name)
fmt.Println(p.age)
结构体类型也可以有方法,例如
func (p Person) Greet() {
fmt.Println("Hello, my name is", p.name)
}
这样就可以给结构体类型Person添加了一个Greet方法,使用方法:
p.Greet()
结构体类型也可以继承性质,它可以包含一个或多个其他结构体类型的字段。
结构体类型也可以使用指针来调用方法,如果结构体变量是指针类型,那么可以直接使用"."来调用方法,也可以使用"->"来调用方法
2.10 Go 语言函数
Go 语言最少有个 main() 函数。
可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,返回类型,和参数。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
函数定义
Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
例如:
func add(x int, y int) int {
return x + y
}
上面的代码定义了一个名为add的函数,它接受两个int类型的参数x和y,并返回一个int类型的值。
函数调用:
result := add(1, 2)
Go语言支持函数返回多个值,例如:
func swap(x, y string) (string, string) {
return y, x
}
Go语言还支持命名返回值,例如:
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Go语言还有一种特殊的函数类型,称为闭包(closure),它允许在函数内部定义函数,并且可以访问外部函数的变量。
三、实践练习例子:
第一个是猜数字游戏,通过这个例子,学会了Go语言中一些函数的使用。 第二个是在线词典,通过这个例子,学会了一些工具的使用。 第三个是个Socket5代理。
示例代码: github.com/wangkechun/…
四、课后个人总结:
感觉其实go很多地方都有C/CPP的影子。 我对于go错误处理的内容掌握的不是很好。 错误处理是通过返回一个错误值来实现的。如果没有错误,错误值为nil。 在基础知识点上,基本都已经掌握住了。也通过实战案例课程,学会了去应用这些基础知识。但仍然需要加强练习去巩固语法。