这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
一、学习准备
为了帮助一些还没有安装go的朋友,这边提供教程和工具。
环境安装(win10安装)
1.进入网址进行windows10版本下载并安装
地址:<https://golang.google.cn/dl/>
选择.msi文件下载安装
2.在cmd修改相关环境
set GO111MODULE=on
set GOPROXY=https://goproxy.cn
相关说明配置:
GOPATH: Go项目的位置,现在我们用GO MOD来管理项目
GOROOT: 这个就是我们的go的安装路径
3.VSCode相关配置
按ctrl+shift+p 调出命令面板,输入go install tools 选Go: Install/Update Tools
本地展示图:
4.VsCode的插件推荐
- code runner
- go
- tabnine
5.在线平台
如果你有 github 的话,可以很方便地使用 gitpods.IO 的在线编程环境来试用 golang 。
只需要浏览器打开 gitpod.io/#github.com… ,用你的 github 账号登录,就可以打开这个课程的示例项目开始编码 。
二、GO语法基础
Go 语言
-
package main 代表这个文件属于 main 包的一部分,main 包也就是程序的入口包。
-
通过import导入了标准库里面的包、如FMT包。这个包主要是用来往屏幕输入输出字符串、格式化字符串。
-
import 下面是 main 函数,main 函数的话里面调用了 fmt.Println 输出 helloword 要运行这个程序的话,我们就直接
go run 文件名.go。 -
如果我们想编译成二进制的话,可以在 go build 来编译。编译完成之后直接通过指令
./文件名就可以运行。
A. 基础语法 - 变量和常量
go语言是一门强类型语言,每一个变量都有它自己的变量类型。 常见的变量类型包括
- 字符串
- 整数
- 浮点型
- 布尔型等等。
变量的声明有两种方式:
1. 通过 var name string = "" 这种方式来声明变量,声明变量的时候,一般会自动去推导变量的类型。如果有需要,你也可以显示写出变量类型。
2. 使用变量 冒号 := 等于值。
常量的声明:
大致与变量一样,仅仅将 **var** 改成 **const**
注意: go语言里面的常量,它没有确定的类型,会根据使用的上 下文来自动确定类型
B. 基础语法 - if
- go 中 if 后面没有括号,即使你写括号的话,那么在保存的时候编辑器会自动把你的括号去掉。
- go 中的 if 后面必须接大括号,不能像 C 或者 C++语言直接把 if 里面的语句同一行。
PS: go 去掉了大部分控制语句中需要使用表达式的地方的括号,如 if, for, switch 等。
C. 基础语法 - 循环
- go语言没有 while、do while循环,只有唯一的 for 循环
- 最简单的 for 循环是 for 后面什么都不写,是一个死循环。
- 循环途中可以使用 break 跳出,也可以使用经典的三段循环,这三段,任何一段都可以省略。
PS:可以使用 break 和 continue 来跳出或继续循环。
D.基础语法 - switch
-
与 C 或者 C++ 比较类似,与if与for一样,加变量名而不需要括号。
-
相比 C 或者 C++ , go语言里面的 switch 功能更强大。
强大的点在于:在C++里面,switch case如果不显示加 break 的话会继续向下运行,但是在go语言中不需要添加break;
- 在go语言中,我们可以使用任意的变量类型,甚至可以用来取代任意的 if else 语句。
- 不仅如此,你可以在 switch 后面不加任何的变量,然后在 case 里面写条件分支,这使得代码相对于ifelse更为清晰。
E. 基础语法 - 数组
数组定义:一个具有编号且长度固定的元素序列。
- 对于一个数组,可以很方便地取特定索引的值或者往特定索引取存储值,可以直接打印一个数组。
- 在真实的业务代码里面,很少直接使用数组,因为它的长度是固定的,我们用的更多的是
切片。
F. 基础语法 - 切片
切片不同于数组,它可以任意的更改长度,同时也具有更多丰富的操作。
如,
- 使用 make 来创建一个切片,可以像数组一样去取值,使用 append 来追加元素。 注意 append 的用户,需要把 append 的结果赋值为原数组。
slice的原理实际上是它存储了一个长度和一个容量,加一个指向一个数组的指针,在你执行 append 操作的时候,如果容量不够的话,会扩容并且返回新的 slice 。- slice 初始化的时候可以指定长度。
- slice 拥有像 python 一样的切片操作(左开右闭),例如 [2:5] 这个代表去除第二个到第五个位置的元素,不包括第五个元素
- 不同于python,这里不支持负数索引。
G. 基础语法 - map
在其他的编程语言中,它常被叫做哈希或者字典。
在go语言中,map 是实际使用过程中最频繁的数据结构。
- 使用 make 来创建一个空的 map ,这里会需要两个类型,第一个是 key 的类型,另一个是 value 的类型。
- 可从里面去存储或取出键值对,可以用delete从里面删除键值对。
package main
import "fmt"
func main() {
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
fmt.Println(m["unknow"]) // 0
r, ok := m["unknow"]
fmt.Println(r, ok) // 0 false
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
需要注意 golang 中的 map 是完全无序的,遍历的时候不会按照字母进行排序,也不会按照插入顺序输入,而是随机顺序
H.基础语法 - range
对于一个 slice 或 map ,我们可以通过 range 来快速遍历
这样可以使得代码更加简洁。
range 遍历的时候,对于数组会返回两个值(第一个是索引,第二个是对应位置的值)。如果我们不需要索引的话,可以使用下划线来忽略。
I. 基础语法 - 函数
golang 函数中和其他语言不同的是,变量类型是后置的。
函数原生支持返回多个值。
在真实业务的go语言,逻辑代码里面几乎所有的函数都返回两个值: 第一个是返回结果 第二个值是一个错误信息。
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res) // 3
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // A True
}
J. 基础语法 - 指针
golang中的指针,相比 C 和 C++ 里面的指针,支持的操作很有限。
指针的一个重要用途就是对于传入参数进行修改。
可以看下面的代码,例子中add2函数中试图把一个变量+2,但是单纯像该函数中的写法是无效的,因为传入函数的参数实际上是一个拷贝,+2也只是对拷贝的+2,对实际的值没有起作用。
如果要使其起作用,就要将该类型写成指针类,同时也要类型匹配,下图中add2ptr函数,调用的时候会增加一个 & 符号。
package main
import "fmt"
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 1
add2(n)
fmt.Println(n) // 3
add2ptr(&n)
fmt.Println(n) // 用到了指针,n值不为1,已经加了2了,显示为5
}
K. 基础语法 - 结构体
结构体定义:带类型的字段的集合。
例如,下面代码中 user 结构包含了两个字段,name 和 password。
- 可以用结构体的名称去初始化一个结构变量,构造的时候需要传入每个字段的初始值。
- 可以用这种键值对的方式去指定初始值,这样可以只对一部分字段进行初始化。
- 能支持指针,这样能够实现对于结构体的修改,也可以在某些情况下避免一些大结构的拷贝开销。
package main
import "fmt"
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d) // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
fmt.Println(checkPassword(a, "haha")) // false
fmt.Println(checkPassword2(&a, "haha")) // false
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword2(u *user, password string) bool {
return u.password == password
}
L. 基础语法 - 结构体方法
在golang中可以为结构体定义方法,类似于其他语言里面的类成员函数。
从上面代码中可以看到:checkPassword 的实现,从一个普通函数改成了结构体的方法,这样用户可以使用 a.checkPassword() 这样调用,具体的代码修改:把第一个参数加上括号,写到函数名称前面。
package main
import "fmt"
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
实现结构体的方法
- 带指针
- 不带指针
区别:如果带指针,那么你就可以对这个结构体去做修改,否则你实现的操作仅仅是一个拷贝,无法对结构体进行修改。。
M. 基础语法 - 错误处理
符合go语言习惯的做法:
使用一个单独的返回值来传递错误信息
在函数里面,我们可以在函数的返回值类型里面,增加一个error,代表这个函数可能返回错误。
在函数实现的时候,return需要同时return两个值。
- 如果出现错误的话,就可以return nil 和一个 error 。
- 如果没有的话,那么就返回原本的结果和 nil。
N. 基础语法 - 字符串操作
在标准库 strings 包里面有很多常用的字符串工具函数
- contains 判断一个字符串里面是否有包含另一个字符串
- count 字符串计数
- index 查找某个字符串的位置
- join 连接多个字符串
- repeat 重复多个字符串
- replace 替换字符串
- 等等
O. 基础语法 - 字符串格式化
在标准库的 FMT 包里面有很多的字符串相关的方法。
go的printf类似于C中的printf函数,不同的是, 在go语言中,
- 可以使用
%v来打印任意类型的变量,不需要区分数字字符串等其他类型。 - 可以使用
%+v来打印详细的结果,%#v则更加详细。
P. 基础语法 - JSON 处理
go中的 JSON 操作非常简单,对于一个已有的结构体——只要保证每个字段的第一个字母是大写即公开字段:
- 那么这个结构体就能用 JSON.marshaler 去序列化;变成一个 JSON 的字符串。
- 序列化之后的字符串也能够用 JSON.unmarshaler 去反序列化到一个空的变量里面。
这样默认序列化出来的字符串,它的风格是大写字母开头,而不是下划线,可以在后面用 json.tag 等语法来修改输出 JSON 结果里面的字段名,代码如下所示。
type userInfo struct {
Name string
Age int `json:"age"`
Hobby []string
}
Q. 基础语法 - 数字解析
字符串和数字之间的转换是如何进行的。
在 go 语言当中,关于字符串和数字类型之间的转换都在 STR.conv 这个包下,这个包是 string.convert 这两个单词的缩写。
-
可以使用 parseInt 或者 parseFloat 来解析一个字符串。
-
可以使用 Atoi 把一个十进制字符串转换成数字,可以用 itoA 把数字转换成字符串。
-
如果输入不合法,那么这些函数都会返回 error。
R. 基础语法 - 进程信息
在 go 中,我们能够用 os.argv 来得到程序执行的时候的指定命令行参数。
但其实可能大家用的频率不高。
S. 基础语法 - 时间处理
-
在go语言里面最常用的就是 time.now() 来获取当前时间
-
可以用 time.date 去构造一个带时区的时间,构造完的时间(具有一定格式)
-
能用点 sub 去对两个时间进行减法,得到一个时间段,得到时间段后可以写相应的Minutes(),Seconds()……
-
可以用 .UNIX 来获取时间戳,可以作为时间参数值设置随机种子
三、实例
3.1 猜数字
3.2 在线词典
3.3 Socks5 代理
需要大家好好听课,然后研究透三个例子。
四、总结
认真对待课程,有选择性的听课,达到高效学习的效果,互勉加油!