这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
Go 语言上手-基础语言
什么是 Go 语言|Go 语言的特点
- 高性能、高并发
- 语法简单,学习曲线平缓。Go语言类似于C语言,但进行了诸多语法简化,如去掉了while循环,只保留了for循环。
- 有丰富的标准库。进行一些基本的开发不需要调用第三方的库,安全性更高。
- 有完善的工具链
- 静态链接
- 快速编译,C++er的福音。
- 跨平台性
- 和JVM一样的垃圾回收的功能,无需考虑内存的分配和释放,专注于业务逻辑。
Go 语言入门
Go 语言的开发环境
1. 下载GOlang。
1)浏览器输入 go.dev 打开 Golang 官网,点击 download 按照提示就可以安装Golang
2)可以尝试使用 Golang 中国的镜像 https://studygolang.com/dl 。
3)如果访问 github的速度非常慢的话,你可以配置 gomod proxy,按照提示打开 https://goproxy.cn/
2. 使用VScode或者其他IDE编辑器
1)安装 vsCode,直接从官网下载安装即可,安装完成之后,需要在左边扩展里面搜索 Go 插件然后安装
2) Goland 是由 JetBrains 公司开发的一个新的商业 IDE。Goland 是一个收费软件,我们可以直接从官网下载。在校学生可以申请免费的教育许可证。
3)使用 gitpods.IO 的在线编程环境来试用 golang,只需要浏览器打开 https://gitpod.io/#github.com/wangkechun/go-bv-example。
用github账号登录即可试用。
3. 配置环境变量
Go 语言基础语法
体验 Go 的第一个程序:Hello World!
package main
import "fmt"
func main(){
fmt.Println("Hello World!")
}
Go 语言的变量类型:
- Go语言是一门强类型语言,每个变量都有它自己的变量类型。
- 常见的变量类型包括:字符串 整数 浮点型、布尔型等。
- Go语言的字符串是内置类型,可以直接通过加号拼接,也能够直接用等于号去比较两个字符串。
- Go语言大部分运算符的使用和优先级都和 C 或者 C++ 类似,这里就不再概述。
变量的声明两种方法
var name int = 2
name := 3 // Go语言中不需要加分号!
常量的声明
const s string = "constant" //就是把 var 改成const
const h = 500
const i = 3e20 / h //Go语言里面的常量没有确定的类型,会根据使用的上下文来自动确定类型
Go 语言中 if-else、switch 和 for 循环
- Golang中if 后没有括号,如果你写有括号,那么在保存时编译器会去除你的括号。
- if 和 else 后边必须带有花括号,不能将代码和if写在同一行。
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
switch 后不用括号,并且每一行结尾会默认加break。
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
default:
fmt.PrintLn("other")
}
- Go语言只有唯一的一种for循环。
- 最简单的 for 循环就是在 for 后面什么都不写,代表一个死循环。
- 也可以使用经典的 C 循环,这中间三段,任何一段都可以省略。
- 可以用 break 或者 continue 来跳出或者继续循环
for {
fmt.Println("loop")
break
}
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
Go 语言的切片:
- 切片是一个可变长度的数组
- 切片是引用传递,数组是值传递。
- 可以任意时刻更改切片的长度。切片可以用make创造,并且分配容量。
- 切片可以用append追加容量和数值,增加后必须要有一个接收值,对于原切片并不会改变。
注意: Go 中 slice 实际上是存储了一个长度加容量加上一个指向数组的指针。append 的过程中该切片容量不够,则会发生扩容,这个时候就需要返回一个新的切片,所以必须赋值回去。
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s[2]) // c
fmt.Println(s) // [a b c d e f]
fmt.Println(s[2:5]) // 表示打印 slice 中从下标区间[2,5)的元素,即 c d e
fmt.Println(s[:5]) // 表示打印 slice 中从下标区间[0,5)的元素,即 a b c d
fmt.Println(s[2:]) // 表示打印 slice 中从下标区间[2,末尾)的元素,即 c d e f
可以用 copy 拷贝切片数值。
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]
也可以直接初始化
good := []string{"g","o","o","d"}
Go语言中的map
map[key]value的数据类型
map["one"] = 1
map["two"] = 2 // 写入
fmt.Println(m) // map["one":1 "one":2]
fmt.Println(m["one"])// 读取
r, ok := m["unknown"]// r 为接收 value, ok 用来判断 map 中是否有这个key存在。
delete(m, "one") // 通过delete来删除map中的key
m2 := map[string]int{"NO1":1, "NO2":2}
var m3 = map[string]int{"NO1":1, "NO2":2}
注意:map中的数据是完全无序的,他不会按照输入的先后顺序输出。
Go 语言中的 range
- 使用 range 可以快速遍历
- 遍历数组的时候会返回两个值,第一个值为数组下标,第二个值为数组下标所对应的值。
- 遍历 map 的时候 第一个返回值是 key 第二个值是 value ( map 是随机的)
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) // b B; a A 可能是无序的
}
Go 语言中的函数
- Go 语言中函数变量类型写在变量之后,返回值类型也写在最后,开头必须用func
- Go 语言中的指针主要作用就是修改值传递为引用传递,使函数中的内容得到全局修改。
- Golang 里面的西数原生支持返回多个值。在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是返回结果,第二个值是一个错误信息
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
Go 语言中的指针
- Go 语言也支持指针。相比 C 和 C++ 里面的指针,支持的操作很有限。指针的一个主要用途就是对于传入参数进行修改。
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main(){
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7
}
Go 语言中的结构体
// 结构体的定义方法
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() {
//结构体的快速设置变量以及赋值的方法
c := user{name: "wang"}
c.password = "1024"
c.resetPassword("2048")
fmt.Println(c.checkPassword("2048")) // true
}
注意:
- 结构体也是一种值传递。如果想要修改传入的数据需要借助于指针。结构体方法和函数不同。
- 注意引用的方法首字母一定要大写。在引用其他包的时候,所定义的函数或方法如果首字母是小写,则只可以在原包中使用而无法被其他包所调用。
Go 语言中的错误处理
- 在定义一个函数时,可以返回一个 error 错误类型(需要引入 error 包)如果发生了错误就返回一个错误信息,否则返回一个空值。
- 在调用这些定义了error返回值的函数时,也需要接收两个值,判断是否错误时,只需判断error的返回值是否为nil。
Go 语言中的字符串操作
- strings.Contains 判断一个字符串中是否包含另一个字符串
- strings.Count 符串计数
- strings.Index 判断另一个字符串在这个字符串中首次出现的下标位置
- strings.Join 在指定位置的字符串中加入某些字符串
- strings.Repeat 重复打印n次字符串
- strings.Replace 把全部的e替换为E,-1表示全部替换 正数表示替换几个
- strings.Split 替换指定字符串为空
- strings.ToLower 打印小写的字符串
- strings.ToUpper 打印大写的字符串
- 一个中文占据3个字节
fmt.Println(strings.Contains(a, "ll")) // true
fmt.Println(strings.Count(a, "l")) // 2
fmt.Println(strings.HasPrefix(a, "he")) // true
fmt.Println(strings.HasSuffix(a, "llo")) // true
fmt.Println(strings.Index(a, "ll")) // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
fmt.Println(strings.Repeat(a, 2)) // hellohello
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo
fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
fmt.Println(strings.ToLower(a)) // hello
fmt.Println(strings.ToUpper(a)) // HELLO
Go 语言中的字符串格式化
在标准库的 fmt 包里面有很多的字符串格式相关的方法,比如 printf 这个类似于 C 语言里面的printf 函数。不同的是,在go语言里面的话,你可以很轻松地用 %v 来打印任意类型的变量,而不需要区分数字字符串。你也可以用 %+v 打印详细结果,%#v 则更详细。
type point struct {
x, y int
}
s := "hello"
n := 123
p := point{1, 2}
fmt.Printf("s = %v\n", s) // s = hello
fmt.Printf("n = %v\n", n) // n = 123
fmt.Printf("p = %v\n", p) // p = {1 2}
fmt.Printf("p = %+v\n", p) // p = {x:1 y:2}
fmt.Printf("p = %#v\n", p) // p = main.point{x: 1, y:2}
Go 语言中的json
- 对于字段首字母大写的结构体,都可以用json.Marshal将其序列化。
- 可以使用json.Unmarshal(序列化, &结构体变量)进行反序列化。
Go 语言中的时间处理
- time.Now()快速获取当前时间。
- time.Data()构造一个带时区的时间。
- 可以用sub来对时间进行一个减法,然后获得时间差
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
diff := t2.Sub(t)
fmt.Println(diff) //1h5m0s
- Format格式化时有一个特定的时间 :2006-01-02 15:04:05
Go 语言中的数字解析
在 Go 语言当中,关于字符串和数字类型之问的转换都在 strconv 这个包下,这个包是 string convert 这两个单词的缩写。
- 可以用 parselnt 或者 parseFloat 来解析一个字符串。parseint 参数
- 我们可以用 Atoi 把一个十进制字符串转成数字。可以用 itoA 把数字转成字符串。如果输入不合法,那么这些函数都会返回error
package main
import (
"fmt"
"strconv"
)
func main(){
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234
n, _ := strconv.ParseInt("111", 10, 64) // 第二个参数指定生成几进制
fmt.Println(n) // 111
m, _ := strconv.Atoi("123")
fmt.Println(m) // 123
n2, err := strconv.Atoi("AAA")
fmt.Println(n2) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}
Go 语言中的进程信息
在 Go 里面,我们能够用 os.argv 来得到程序执行的时候的指定的命令行参数。 比如我们编译的一个二进制文件,command。后面接 abcd 来启动,输出就是 os.argv 会是一个长度为 5 的slice ,第一个成员代表二进制自身的名字。 我们可以用 so.getenv 来读取环境变量exec。
总结
本文主要对第五届青训营基础班的后端入门课程进行了总结,很多内容摘自《Go 语言原理与实践》课程的内容,旨在对本次青训营课程做笔记记录课程所学的内容。虽然我有很多地方不懂,但是我会尽力做到要求,力求本次青训营能学到一些东西。