[ 后端与 Go | 青训营笔记 ]

96 阅读6分钟

[ 后端与 Go | 青训营笔记 ]

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

课前:vscode Go 环境配置

备份用,以防不时之需。

安装 Go 本体

安装在自定义文件夹,最后在 cmd 输入 go version 查看是否安装成功,显示版本号即可。

Go 环境变量的配置

  1. 设置 GOPATH 路径,即工作区路径;
 go env -w GOPATH=工作区路径
  1. 打开 GoMOD,配置代理,避免kxsw;
 go env -w GO111MODULE=on
 go env -w GOPROXY=https://goproxy.cn,direct
  1. 在 vscode 中下载 Go 拓展;
  2. 在 vscode 中搜索 Go:Install/Update Tools ,下载全部环境依赖。

使用 Go\ Modules

  1. 在工作区创建文件夹 Src ,用于保存源代码;
  2. 在文件夹 Src 中创建 hello 文件夹;
  3. 在终端进入 hello 文件夹,并创建 go.mod 文件
 cd $GOPATH/src/hello
 go mod init 组件名,没有组件名将创建失败

最后,配置 Launch.json 即可实现在 vscode 上对 Go 进行调试。

课内:Go 基础

重点

  1. 入门

    开发环境 | 基础语法 | 标准库

  1. 实践

猜谜游戏 | 在线词典 | sockss代理

细节

  1. 基础语法
  • 第一个 go 程序
 package main //说明该文件属于main包
 ​
 import {
     "fmt" //引入包,用于屏幕输入输出,格式化字符串
 }
 ​
 func main() {// main函数
     fmt.Println("Hello")
 }

使用 go run 文件名.go 可以直接运行,使用 go build 可以编译为二进制文件,后可以使用 ./文件名 直接运行

  • 变量

常见类型为字符串、整数、浮点型、布尔型;

字符串类型为内置类型,可以直接用加号拼接,类似 cpp string

以下为类型声明

 var a = "asdad" //自动识别类型
 ver a1, a2 int = 1, 2 //主动声明类型
 b := "asdada" //另一种声明方式
 var c float64
 var d = float32(c) // 强制类型转化
 const e = "asdad" //声明常量
  • if\else

条件无需括号,必须带大括号

 if a > b {
     
 }else if a < b {
     
 }
  • 循环

只有 for 循环。

 for { //死循环,只能通过break退出
     break;
 }
 for i := 1;i <= 10;i++ { //同c
     break;
 } 
  • switch:不需要括号,不用每个都break,被判断者可以是任意类型,可以只在case中判断,不需要在switch后面添加变量
 switch {
     case 条件:
     default
 }
  • 数组
 var a [5]int
  • slice切片

切片不同于数组可以任意更改长度,可以像数组一样去取值,使用 append 来追加元素,必须把 append 的结果赋值为原数组。 。slice 拥有像 python 一样的切片操作,比如这个代表取出第二个到第五个位置的元素,不包括第五个元素。不过不同于python,这里不支持负数索引

 s := make([]string ,1)
 s[0] = "a";
 s[0] //访问 
 len(s) //长度
 s = append(s ,"e" ,"f") //追加
 c := make([]string ,len(s))
 copy(c ,s) //复制
 s[0 :2] // a e 切片
  • map 类比 STL

可以用 make 来创建一个空 map ,这里会需要两个类型, key 的类型、 value 的类型,这里是 int 。可以用 delete 从里面删除键值对。 go的map是完全无序的。

 m := make(map[string]int) // string key int val
 var m2 = map[string]int {"one": 1}
 m["one"] = 1
 ftm.Println(m) //map[one:1]
 ftm.Println(m["one"]) // 1
 ftm.Println(m["on"]) // 0
 delete(m ,"one") //删除
  • range

对于一个 slice 或者一个 map 的话,可以用 range 来快速遍历。 range 遍历的时候,对于数组会返回两个值,第一个是索引,第二个是对应位置的值。如果不需要索引的话,可以用下划线来忽略。

 m := map[string]string("a": "A" ,"b" "B") 
 for k ,v := rang m {
     ftm.Println(k ,v) // b Ba A
 }
  • 函数

Go 和其他很多语言不一样的是,变量类型是后置的。 Go 里面的函数原生支持返回多个值。在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息。

 // 参数 返回值
 func s(m map[string]string ,k string) (v string ,ok bool) {
     v ,ok = m[k]
     return v ,k;
 }
 ​
 func main() {
     v ,ok := s(map[string]string{"a": "A"}, "a")
     ftm.Println(v ,ok) // A true
 }
  • 指针

支持的操作很有限。指针的一个主要用途就是对于传入参数进行修改

 func add(n *int) {// 传地址
     *n += 2
 }
 ​
 func main() {
     n := 5
     add(&n)
 }
  • 结构体
 type use struct {// 声明
     name string
     pass string
 }
 ​
 func main() {
     a := use(name:"a" ,pass:"b")
     b := use("A" ,"B")
 }
  • 结构体方法

利用以下的方式可以声明结构体方法,与cpp不相同的是,结构体方法说明的位置在结构体之外。

 type use struct {// 声明
     name string
     pass string
 }
 ​
 func (u use) check(pass string) bool{
     return u.pass == pass
 }
 ​
 // 只有指针才能对原结构体修改
 func (u *use) check(pass string) string{
     return u.pass += "A"
 }
  • 错误处理

函数的返回值类型里面后面加一个 error, 代表函数可能会返回错误。 需要同时 return 两个值,如果出现错误的,return nil 和一个 error。如果没有错误,return 原本的结果和 nil。

 import {
     "error"
     "fmt"
 }   
 ​
 type use struct {// 声明
     name string
     pass string
 }
 ​
 func find(uses []use ,name string) (v *use, err error) {
     for _ ,u := range uses {
         if u.name == name {
             return &u ,nil //返回结构体 和空
         }
     }
     return nil ,error.New("err") //返回空 和错误信息
 }
 ​
 func main() {
     u ,err := find([]use{{"w", "1024"}} ,{"w"})
     if err != nil {//根据返回值做出判断
         fmt.Println(err)
         return 
     }else {
         fmt.Println(u.name)
     }
 }
 ​
  • 字符串操作
 import {
     "fmt"
     "strings"
 }
 ​
 func main() {
     a := "hello"
     strings.Contain(a ,"ll") //判断是否为子模式
     strings.Count(a ,"l") //子模式数量
     // 同理
     HasPrefix //查找前缀
     HasSuffix //查找后缀
     Index //子模式首位置
     Join([]string{"he" ,"llo"} ,"-") //数组插入
     Repeat(a ,2)//重复两次
             a ,b ,c string n int
     Replace(a ,"e" ,"E" ,-1) // a的前n个不重复子串b换为c ,若 n < 0,则替换全部字串
     Split("a-b-c" ,"-") //用空格代替所有-
     ToLower(a) //全小写
     ToUpper(a) //全大写
 }
  • 字符串格式化

字符串格式化。在标准库的 FMT 包里面有很多的字符串格式相关的方法,用 %v 来打印任意类型的变量,而不需要区分数字字符串。也可以用 %+v 打印详细结果,%#v 则更详细。

 type po struct {
     x ,y int
 }
 ​
 func main() {
     s := "h"
     n := 1
     p := po{1 ,2}
     fmt.Printf("%v%v",s ,n) //h1
     fmt.Printf("%+v %#v",p ,p) //x:1 y:2 main.po{x:1 y:2}
     f := 3.1415
     fmt.Printf("%.2v",f) //3.14
 }
  • 时间处理

最常用的就是 time.now() 来获取当前时间,也可以用 time.date 去构造一个带时区的时间。有很多方法来获取这个时间点的年月日小时分钟秒,然后也能用点 sub 去对两个时间进行减法,得到一个时间段。时间段又可以去得到它有多少小时,多少分钟、多少秒。在和某些系统交互的时候,经常会用到时间戳。可以用 .UNIX 来获取时间戳。 time.format time.parse

  • 数字解析

关于字符串和数字类型之间的转换都在 strconv 这个包下,这个包是 string convert 这两个单词的缩写。 可以用 parseInt 或者 parseFloat 来解析一个字符串

参数1 数字的字符串形式 参数2 数字字符串的进制 比如二进制 八进制 十进制 十六进制 参数3 返回结果的bit大小 也就是int8 int16 int32 int64

若输入不合法,这些函数会返回error

 f ,_ = strconv.ParseInt("0x1000", 2, 64)
 n ,err = strconv.Atoi("AAA") //字符串转int 报错

总结

学习到了很多 go 语言的基础知识,部分内容由于缺乏实践导致难以理解、或不知道有什么用,在后面的学习中争取理解。