走进Go基础语言 | 青训营笔记

72 阅读5分钟

走进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代理服务器。对于多并发多线层相关内容还需要更深刻的学习。

五、引用参考