走进Go基础语言 | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第1天。
一、本堂课重点内容
- Go语言的特点
- Go语言的基础语法
- 三个Go语言入门小程序
二、详细知识点介绍
1. Go语言基础
1.1 Go语言特点
- 高性能、高并发
- 性能高
- 使用标准库、基于标准库的三方库即可高并发
- 语法简单、易学
- 丰富的标准库
- 类python标准库,稳定,享受语言迭代的性能优化
- 完善的工具链
- 编译、错误检测
- 单元测试、性能测试、代码覆盖率
- 静态链接
- 无需附加任何东西即可运行
- 镜像大小极小
- 快速编译:性能好
- 几秒内编译完成
- 跨平台
- windows/macos
- 安卓/ios/其他平台
- 垃圾回收
- 无需考虑内存分配释放
2. Go语言入门
2.1 基础语法
package main
//导入标准包fmt,向屏幕输入输出字符串,编辑字符串
import (
"fmt"
)
//main函数,输出hello world
func main(){
fmt.Println("hello world")
}
//编译
go run main.go
go build main.go
2.2 基础语法 - 变量&常量
- 字符串:可以使用+拼接
var a = "initial" g := a + "foo"; - int
var b,c int = 1,2 - boolean
var d = true - float 浮点
//默认为0 var e float64 f := float32(e) - 常量:const
2.3 基础语法 - if else
- 类似其他语言的if-else, 但特点在于condition不需要左右括号,同时不能将大量条件写在同一行,而应该写在两行(使用;连接)
// 不能写到同一行
if num%2==1; num<0 {
xx
} else if num>10 {
xx
}
2.4 基础语法 - 循环
- 只有for循环,不加条件时会持续执行;加条件不需要括号
//=while(true)
for {
xx
break;
}
//正常for loop
for j:=7;j<9;j++{
xx
if n%2==0 {
continue
}
xx
}
2.5 基础语法 - switch
- 类似其他语言的switch, 但特色是执行完一个case后不需要break,而不会进入其他的case;
switch a {
case 1:
xx
case 2:
xx
case 3,4:
xx
default:
XX
}
//case内的条件分枝
switch {
case t.hour()<12:
xx
default:
xx
}
2.6 基础语法 - 数组
- 与其他语言数组基本相同
var a [5]int
a[4] = 100
len(a)
//2d数组的定义
var twoD [2][3]int
2.7 基础语法 - 切片
- 基于数组的切片 类似python
//创建一个数组的切片
s := make([]string, 3)
//需要赋值回原切片
s = append(s, "d")
//copy一个切片
copy(c, s)
s //[a b c d e f]
s[2:5] //[c d e]
s[:5] //[a b c d e]
s[2:] //[c d e f]
2.8 基础语法 - map(= python.dictionary)
- 类似hash表,key-value pair存储
//创建一个从字符映射到int数字的map
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
//unknown value is 0
//删除by key
delete(m, "one")
2.9 基础语法 - 函数
//返回两个值,一个为实际返回值,一个为错误信息
func exists(m map[string]string, k string)(v string, ok bool){
v, ok = m[k]
return v, ok
}
2.10 基础语法 - 指针
//如果不用指针 则传入参数为拷贝值 无法修改在其他函数中的值
//因此需要使用指针 在新函数中修改对应地址的值
func add2ptr(n *int){
*n += 2
}
2.11 基础语法 - 结构体
//带类型的字段集合
type user struct{
name string
password string
}
//结构体函数方法
func (u user) checkuser(password string) bool{
return u.password = password
}
func (u *user) changeuser(password string) {
u.password = password
}
2.12 基础语法 - 错误处理
- 在函数返回值中加入error
- return errors.New("not found")
2.13 基础语法 - 字符串操作
- strings包中有基础的字符串操作
a:="hello"
strings.Contains(a, "ll") //true
strings.Count(a, "l") //2
strings.HasPrefix(a, "he") //true
strings.HasSuffix(a,"llo") //true
strings.Index(a, "ll") //2
strings.Join([]string{"he","llo"}, "-") //he-llo
strings.Repeat(a,2) //"hellohello"
strings.Replace(a, "e", "E", -1) //"hEllo"
strings.Split("a-b-c", "-") //[a b c]
strings.ToLower(a) //"hello"
strings.ToUpper(a) //"HELLO"
len(a) //5
2.14 基础语法 - 字符串格式化
fmt.Println(s, n)
//%v支持所有类型变量 无需变化
fmt.Printf("s=%v\n", s)
2.15 时间处理
- time包
now := time.Now()
now.Year()
now.Month()
now.Day()
now.Hour()
now.Minute()
//使用特定字符串进行parsing
time.Format("2006-01-02 15:04:05")
time.Unix() //获得时间戳
2.16 数字解析
- strconv包
strconv.ParseFloat("1.234", 64) //1.234
strconv.ParseInt("111",10,64) //111
strconv.ParseInt("0x1000", 0, 64) //4096
strconv.Atoi("123") //123
strconv.Atoi("AAA") //error parsing "AAA" invalid syntax
2.17 进程信息
- os包
//获取修改运行路径
os.Genenv("PATH")
os.Setenv("AA","BB")
//启动子进程 获取输入输出
exec.Command("grep, "127.0.0.1", "/etc/hosts").CombinedOutput()
三、实践练习例子
1. 猜谜游戏
- 生成随机数
- math/rand包,定义变量maxNum
- rand.Intn(maxNum)每次生成相同的值
- 需要使用time做随机数种: rand.Seed(time.Now().UnixNano())
- 读取用户输入
- os.Stdin读取输入
- 使用bufio.NewReader读取输入
- 使用read.ReadString('\n')读取字符串
- 实现判断逻辑 if-else
- 实现游戏循环:出错后执行下一次输入
2. 在线词典抓包
- curl发送网络请求
- 生成req的相关header
- 解析response,输出
- 解析json包输出结果
3. socks5代理
- socks5原理
- client与代理服务器建立连接,发送请求到代理服务器
- 代理服务器与host建立连接(三次握手),发送请求收到响应,将状态返回client
- client发送数据,代理服务器中转数据,host返回结果,代理服务器返回结果
- 实现
- TCP server 接收请求,启动线程处理连接
- auth 确认协议、认证、版本号
- 请求阶段:发送包到server
- relay阶段:创建TCP连接,实现浏览器和服务器双向数据转发,创建两个goroutine(线程)进行双向转发
四、课后个人总结
- 本节课介绍了go语言的基本语法。go语言在大体上与其他常用语言类似,使用的逻辑等也比较相同。go语言中的循环只有for逻辑一种,if-else只支持单行逻辑判断,如果需要实现多行逻辑需要分号隔开。
- 本节课比较困难的内容为最后的三个小例子,特别是实现socks5代理服务器。对于多并发多线层相关内容还需要更深刻的学习。