这是我参与「第五届青训营 」笔记创作活动的第1天
前言
Go 语言在很多特性上和C语言非常相近。若有C语言基础,那么本文的内容阅读起来将会非常轻松;如果读者没有C语言基础也没关系,因为本文内容非常简单易懂。
这节课首先从 Go 语言基本特征、应用优势等方面介绍了 Go 语言,讲解了一些 Go 语言的基础语法,并编写了一个在线的命令行词典与一个简单的 SOCKS5 代理服务器,在实战演练中学习到了在 Go 语言中发送请求的方法,练习了前面学到的基础语法。
什么是Go
Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。
Go语言有时候被描述为“C 类似语言”,或者是“21 世纪的C语言”。Go 从C语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等很多思想,还有C语言一直所看中的编译后机器码的运行效率以及和现有操作系统的无缝适配。 Go语言的特色:
- 简洁、快速、安全
- 并行、有趣、开源
- 内存管理、数据安全、编译迅速
第一个 Go 程序
如同我们学习其他语言一样,接下来我们来编写第一个 Go 程序,Hello World 程序。
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
要执行 Go 语言代码可以使用 go run 命令。
执行以上代码输出:
$ go run hello.go
Hello, World!
此外我们还可以使用 go build 命令来生成二进制文件:
$ go build hello.go
$ ls
hello hello.go
$ ./hello
Hello, World!
基础语法
变量
变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。变量可以通过变量名访问。Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
声明变量的一般形式是使用 var 关键字:
var identifier type
可以一次声明多个变量:
var identifier1, identifier2 type
但是 Go 语言支持通过等号右侧的代码进行类型推断,并不强制在声明时表面变量的类型,在声明变量时可以这样写:var a = 1 这一行代码代表声明了一个 int 类型的变量 a 赋值为 1。当然,如果你不想在变量声明时指定初始,编译器无从猜测,那就必须为变量指定类型。在这种情况下,Go 语言会和 java 类似对变量进行零值初始化。
如果你不想每一次都写 var,那么还有一种简化写法:名字 := 表达式。这种情况下,变量的类型根据表达式来自动推导。但这样不意味无法指定变量类型,在简化写法下要指定变量类型可以通过这样的方式 f := float32(e) ,先将右侧的值强转为需要的类型,再由其进行猜测。
PS: “:=”是一个变量声明语句,而“=”是一个变量赋值操作
说完基础变量的声明,那么再来说说数组。声明数组的写法为 var a [5]int 或者 a[5] = 100。但是在真实的 codeing 中我们很少直接使用数组,因为数组长度无法扩展。我们更常用的是切片。
流程控制
Go支持if;else;else if;switch语句
if else
if 9 % 2 == 1:
print("odd")
else:
print("even")
switch
switch语句在大部分语言中大差不差,所以此处一笔带过,下面说一些不太一样的地方
差别
- Go中的switch case,在每个case中,break是隐式存在的
- Go中的switch case,可以在case中,使用fallthrough关键字继续执行下一条case中的内容 PS:需要注意的是,fallthrough关键字不能出现在最后一个case,且fallthrough在执行下一条case时,不会 判断是否满足条件
循环
不同于我所熟知的大多数语言,Go中的循环只有for
我们仍可以定义C-style loop
for initialization; condition; expression{
statement
}
在这段循环中,initialization; condition; expression都是可省略的。
数组
数组的长度是固定且不可改变的,且储存的类型是一致的,也就是说,当在定义一个array时,它的长度就已经确定了。
不止在go,在C#,Java,C/C++中,都是相通的。
int arr[2]; var arr [2]int int[] arr = new int[2]; int[] arr = new int[2];
切片
声明切片:s := make([]string, 3),可以简单将slice理解为一个可变长度的slice,相比数组他也有更多的操作。
slice可以像普通数组一样直接赋值。
s[0] = "a"
s[1] = "b"
s[2] = "c"
复制代码
slice可以用 append 方法直接向slice最后添加元素 s = append(s, "e", "f"),要注意使用 append 方法时必须赋值给原来的slice变量,这是因为容量不够时 append 会扩容返回新的地址。
在创建时slice时也可以指定长度 c := make([]string, len(s)),可以用 copy(c, s) 进行复制。
slice还支持类似 python 中的slice操作,例如:s[2:5]//左闭右开。但与 python 不同的是 Go 中的slice不支持负数索引。
map
map在其他的语言中,可能被称为HashMap(Java)或者Dictionary(C#) Go中,map的定义也是需要用到make
//m := make(map[keytype]valuetype)
//如
m := make(map[string]int)
//存取值时,可以使用m[key] = value
//如
m["a"] = 1
复制代码
PS:Go中的Map是 无序的
函数与指针
在Go中,函数的基本构成是
func funcName(parameter) returnValue{
}
复制代码
像C一样,Go也有指针,存储着内存地址
但与C不同的是,Go 没有 指针运算
i, j := 42, 2701
p := &i
*p = 21
p = &j
*p = *p / 37
复制代码
结构体
Go中结构体的定义格式为
type structName struct {
}
复制代码
eg:
type Vertex struct {
X int
Y int
}
复制代码
结构体亦可以在传参时传入指针
最后
今天的课程带我快速上手了 Go 语言,我学会了基本语法与基本的HTTP请求发送方式,关于最后一个 SOCKS5 代理服务器我还需要反复学习,以更加深入理解。今天的笔记就到此为止,明天继续更新~~