这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记
Go语言基础:字节青训营
Go语言简介
Go语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go 是非常年轻的一门语言,它的主要目标是“兼具 Python 等动态语言的开发速度和 C/C++ 等编译型语言的性能与安全性”。
Go语言是编程语言设计的又一次尝试,是对类C语言的重大改进,它不但能让你访问底层操作系统,还提供了强大的网络编程和并发编程支持。Go语言的用途众多,可以进行网络编程、系统编程、并发编程、分布式编程。
Go的特点和优点
- 高性能,高并发
- 语法简单,学习曲线平缓.Go 从零开始,没有历史包袱,在汲取众多经验教训后,可从头规划一个规则严谨、条理简单的世界。
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
Go语言开发环境推荐
1) Goland
Goland 是由 JetBrains 公司开发的一个新的商业 IDE,旨在为 Go 开发者提供的一个符合人体工程学的新的商业 IDE。Goland 整合了 IntelliJ 平台(一个用于 java 语言开发的集成环境,也可用于其他开发语言),提供了针对Go语言的编码辅助和工具集成。
2) Visual Studio Code(简称VS Code)
是一款由微软公司开发的,能运行在 Mac OS X、Windows 和 Linux 上的跨平台开源代码编辑器。
VScode 安装教程参见:www.runoob.com/w3cnote/vsc…
从扩展管理中安装Go插件
打开 VSCode 的扩展
搜索go插件并安装
配置包管理器Go MOD镜像
go module 是Go语言从 1.11 版本之后官方推出的版本管理工具 类似于pip,国内很多包的下载效果都不好,需要配置镜像代理
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
# 清空缓存
go clean --modcache
# 查看环境信息
go env
Go语言的基础语法
1. hello world
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
要运行这个程序,将这些代码放到 hello-world.go 中并且使用 go run 命令。
2.变量
var a = "initial"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
fmt.Println(g) // initialapple
var 声明 1 个或者多个变量。
var a string = "initial"
fmt.Println(a)
可以申明一次性声明多个变量。
var b, c int = 1, 2
fmt.Println(b, c)
Go 将自动推断已经初始化的变量类型。
var d = true
fmt.Println(d)
声明变量且没有给出对应的初始值时,变量将会初始化为零值 。例如,一个 int 的零值是 0。
var e int
fmt.Println(e)
:= 语句是申明并初始化变量的简写
f := float32(e)
3. if else
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
4.循环
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
5.switch
最常用的方式,带单个循环条件。
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
不带条件的 for 循环将一直执行,直到在循环体内使用了 break 或者 return 来跳出循环
for {
fmt.Println("loop")
break
}
6.数组
var a [5]int
fmt.Println("emp:", a)//创建了一个数组 a 来存放刚好 5 个 int
a[1] = 100//我们可以使用 array[index] = value 语法来设置数组指定位置的值
fmt.Println("set:", a)
fmt.Println("get:", a[1])//用 array[index] 得到值
fmt.Println("len:", len(a)) //使用内置函数 len 返回数组的长度
7. 切片
s := make([]string, 3)//slice 的类型仅由它所包含的元素决定(不像数组中还需要元素的个数)。要创建一个长度非零的空slice,需要使用内建的方法 make。这里我们创建了一个长度为3的 string 类型 slice(初始化为零值)。
fmt.Println("emp:", s)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("set:", s)
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))//len 返回 slice 的长度
s = append(s, "d")//slice 支持比数组更多的操作。其中一个是内建的 append,它返回一个包含了一个或者多个新值的 slice
8.map
m := make(map[string]int)
m["one"] = 1 //使用典型的 make[key] = val 语法来设置键值对
m["two"] = 2
fmt.Println(m) // map[one:1 two:2] 使用例如 Println 来打印一个 map 将会输出所有的键值对。
fmt.Println(len(m)) // 2 //当对一个 map 调用内建的 len 时,返回的是键值对数目
fmt.Println(m["one"]) // 1 //使用 name[key] 来获取一个键的值
fmt.Println(m["unknow"]) // 0
9.range
nums := []int{2, 3, 4}//使用 range 来统计一个 slice 的元素个数
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
10函数
package main
import "fmt"
func add(a int, b int) int { //这里是一个函数,接受两个 int 并且以 int 返回它们的和
return a + b
}
func add2(a, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {//(string, bool) 在这个函数中标志着这个函数返回 2 个值
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)//通过 name(args) 来调用一个函数
fmt.Println(res) // 3
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // A True
}
11.指针
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)//通过 &n 语法来取得 n 的内存地址
fmt.Println(n) // 7
}
12.结构体
type user struct {
name string
password string
}
//这里的 user 结构体包含了 name 和 password 两个字段
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
}
13.错误处理
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {//按照惯例,错误通常是最后一个返回值并且是 error 类型
for _, u := range users {
if u.name == name {
return &u, nil//返回错误值为 nil 代表没有错误
}
}
return nil, errors.New("not found")//errors.New 构造一个使用给定的错误信息的基本error 值
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wang
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
14.字符串操作
package main
import (
"fmt"
"strings"
)
func main() {
a := "hello"
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
fmt.Println(len(a)) // 5
b := "你好"
fmt.Println(len(b)) // 6
}
15.字符串格式化
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p) // {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}
f := 3.141592653
fmt.Println(f) // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
}
16.Json处理
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string
Age int `json:"age"`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // [123 34 78 97...]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}
17.数字解析
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
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}
18 进程
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
// go run example/20-env/main.go a b c d
fmt.Println(os.Args) // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go- build3406981276/b001/exe/main a b c d]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1 localhost
}
编译执行Go程序
使用Go命令编译执行Go程序的例子
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
编译执行
Go指令
可以
go build hello.go
./hello.exe
也可以
go run hello.go
也可以添加VSCode环境,直接使用
包管理
每个go程序都由包构成的,程序从main包的main函数开始运行。编译不包含main包的源文件后,不会得到可执行文件 不同包的源程序需要通过import关键字导入别的包 import 的是目录,建议绝对路径:import “包的路径”。
单行导入:
import "fmt"
多行导入:
import (
“包1的路径”
“包2的路径”
)