[ 后端与 Go | 青训营笔记 ]
这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
课前:vscode Go 环境配置
备份用,以防不时之需。
安装 Go 本体
- 官网下载:golang.org ,需要kxsw,不采用;
- Go 中文网下载:Go下载 - Go语言中文网 - Golang中文社区 (studygolang.com) ,可行,已使用。
安装在自定义文件夹,最后在 cmd 输入 go version 查看是否安装成功,显示版本号即可。
Go 环境变量的配置
- 设置 GOPATH 路径,即工作区路径;
go env -w GOPATH=工作区路径
- 打开 GoMOD,配置代理,避免kxsw;
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
- 在 vscode 中下载 Go 拓展;
- 在 vscode 中搜索 Go:Install/Update Tools ,下载全部环境依赖。
使用 Go\ Modules
- 在工作区创建文件夹 Src ,用于保存源代码;
- 在文件夹 Src 中创建 hello 文件夹;
- 在终端进入 hello 文件夹,并创建
go.mod文件
cd $GOPATH/src/hello
go mod init 组件名,没有组件名将创建失败
最后,配置 Launch.json 即可实现在 vscode 上对 Go 进行调试。
课内:Go 基础
重点
-
入门
开发环境 | 基础语法 | 标准库
- 实践
猜谜游戏 | 在线词典 | sockss代理
细节
- 基础语法
- 第一个 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 B;a 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 语言的基础知识,部分内容由于缺乏实践导致难以理解、或不知道有什么用,在后面的学习中争取理解。