这是我参与「第五届青训营 」笔记创作活动的第1天
本堂课重点内容
- Go语言的特点
- Go语言基础语法
- 实战案例
详细内容介绍
Go语言的特点
- 高性能、高并发
- 语法简单,学习曲线平滑
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
Go语言开发环境的搭建
-
安装golang
golang官网: go.dev/
其它下载地址:golangstudy.com.dl, goproxy.cn
-
安装vscode或goland
Go基础语法
1. hello world
import "fmt"
func main() {
fmt.Println("Hello World!")
}
可使用命令go build main.go编译生成可执行文件。也可以直接使用go run main.go命令运行
2.变量
var a = "hello" //声明了一个 string 类型变量a, 值为"hello",编译器自动推导它的类型为string
var b, c int = 2, 3 //声明了两个int型变量,值默认为0
var d = true //bool型
var e float64 //浮点型
f := float32(e) //省略var关键字,使用 := 声明变量
const s string = "constant" //声明了一个string常量
const h = 50000
const i
- go语言的变量类型有int int16 int32 int64 float32 float64 bool string等
- 用var关键字声明变量,const关键字声明常量
- 给出变量的初始化值,可省略变量类型,由编译器自动推导类型
- 常量数值可以没有类型,被使用时会自适应类型
3 if-else
Go语言的if-else语句与C语言类似,但条件不需要小括号,大括号不可以换行
var maxv int
if a > b { //大括号不可换行
maxv = a
} else {
maxv = b
}
4 循环
Go语言只有for循环,没有while和do while循环。
与C语言一样,可以使用continue继续循环,使用break退出循环。
//死循环
for { //相当于while(true)
fmt.Println("loop")
}
//while循环
i := 0
for i <= 10 {
i++
}
// 计算1 + 2 + 3 + ... + 100
s := 0
for i := 1; i <= 100; i++ {
s += i
}
fmt.Println(s)
5 switch
go语言不需要在每个case最后写break
switch a {
case 1:
fmt.Println("a=1")
case 2:
fmt.Prineln("a=2")
default:
fmt.Println("a!=1 or 2")
}
可以不指定swtich的变量,在每个case的后面写一个条件语句,第一个条件成立的case会被执行。
t = time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
6 数组
//声明数组
var a [5]int
b := [5]int{1, 2, 3, 4, 5}
//二维数组
var twoD [3][3]int
注意不同长度的数组是不同类型的数据。
7 切片
切片(slice)表示一个可变长的的拥有相同类型元素的序列,类型通常写成[]T
s := make([]string, 3) //用make初始化slice,初始长度为3
s[0] = "a"
s[1] = "b"
s[2] = "c"
s = append(s, "d") //向slice后增加一个元素
s = append(s, "d", "e", "f") //增加多个元素
append(s, "d"),如果s还有空间,会直接在s后增加一个元素,如果容量不够,会再开一个新的容量更大slice,因此调用时必须用s = append(s, "d")
8 map
map是散列表的引用,类型是map[K]V,K和V是字典的键和值的类型
可以用make函数来创建一个map: ages := make(map[string]int)
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
r, ok := m["unknown"] //如果map中有键"unknown"则ok返回true,否则ok返回false
delete(m, "one") //从map中删除一个键值对
键的类型必须是可以用==比较的类型
9 range
可以用for和range实现类型python的循环语句,用于遍历数组、slice、map等
nums := []int{2, 3, 4}
for i, num := range nums { // i是下标,num是值,可以用 _ 忽略下标或值
fmt.Println(i, num)
}
m = map[string]int{"one":1, "two":2}
for k, v := range m { //k和v分别是键和值
fmt.Printf("m[%v] = %v\n", k, v)
}
10 函数
go语言定义函数的格式为
func 函数名(参数) 返回值类型 {
return 返回值
}
go语言的函数可以有多个返回值
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 //返回两个值
}
11 指针
go语言的指针与C语言类似。
func add2(n int) {
n += 2
}
func add2ptr(n *int) { // *int为int类型的指针
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(n)
fmt.Println(n) //7
}
Go语言函数参数是按值传递,函数接收的的参数是一个副本,对副本的赋值不会影响原变量。要在函数中改变原变量的值就要使用指针。
12 结构体
定义一个结构体类型
type User struct {
Name string
Password string
}
使用结构体
a := User{Name:"zhangsan", Password:"123456"}
b := User{"lisi", "123"}
fmt.Println(b.Name, b.Password) //用点访问结构体的字段
结构体指针
ptr := &User{Name:"wang5", "aaa"}
fmt.Println(ptr.Name) //指针也可以用点访问结构体的字段
13 结构体方法
定义结构体方法
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关键字后面加个(t T)或(t *T)即可将函数绑定为结构体方法,结构体变量和指针可以用点运算符调用方法。
14 错误处理
go语言的错误处理策略是,函数调用发生错误时返回一个附加的err作为错误值,习惯上将错误作为最后一个结果返回。
func divide(a int, b int) (int, error) {
if b == 0 {
return 0, errors.New("can't divide zero") //发生错误时,返回一个error
}
return a / b, nil
}
func main() {
a := 10
b := 2
c, err := divide(a, b)
if err != nil { //调用divide时发生了错误
fmt.Println(err) //打印错误信息
return
}
}
15 字符串操作
strings包中有一些字符串操作函数
a := "hello"
//是否包含子串
strings.Contains(a, "ll") // true
//子串出现次数
strings.Count(a, "l") // 2
//是否以特定字符串开头
strings.HasPrefix(a, "he") // true
//是否以特定字符串结尾
strings.HasSuffix(a, "llo") // true
//特定子串第一次出现的位置
strings.Index(a, "ll") // 2
//连接多个字符串
strings.Join([]string{"he", "llo"}, "-") // he-llo
//重复字符串
strings.Repeat(a, 2) // hellohello
//替换子串
strings.Replace(a, "e", "E", -1) // hEllo
//分割字符串
strings.Split("a-b-c", "-") // [a b c]
//转换为小写
strings.ToLower(a) // hello
//转换为大写
strings.ToUpper(a) // HELLO
//获取字符串长度(字节数,不是字符数)
fmt.Println(len(a)) // 5
b := "你好"
fmt.Println(len(b)) // 6
16 字符串格式化
可以使用fmt.Printf()函数格式化输出字符串,与C语言的printf()函数类似。可以用%v格式化任务数据类型。用%+v和%#v输出变量的详细信息。
fmt.Printf()格式化输出
fmt.Errorf()格式化输出错误
fmt.Fprintf()格式化输出到特定writer
fmt.Sprintf()格式化并返回string
17 JSON处理
用json.Marshal()将结构体转化成json,用json.Unmarshal()将json转化为结构体。
定义结构体,可以用json注解表示该字段在json中的名字
type Human struct {
Name string `json:"name"`
Age int `json:"age"`
}
用json.Marshal将结构体转化为json,返回值类型是[]byte
a := Human{"Lisi", 22}
buf, err := json.Marshal(a)
if err != nil { //转化发生错误
panic(err)
}
fmt.Println(string(buf))//转化为json字符串输出
可以使用json.MarshalIndent(a, "", "\t")获得具有缩进,更可读的json字符串。
用json.Unmarshal将[]bytejson解析为结构体
var b Human
err = json.Unmarshal(buf, &b)
if err != nil {
pannic(err)
}
18 时间处理
time.Now()获取当前时间,返回值为类型为Time,表示当前时间
time.Date(2023, 1, 20, 22, 30, 30, 30, time.UTC)将指定时间指定为Time类型
t.Format("2006-01-02 15:04:05")格式化时间,将Time类型变量转化为字符串,用"2006-01-02 15:04:05"这个特定时间表示格式。
t.Sub(t1)计算时间t和时间t1的差
time.Parse("2006-01-02 15:04:05", "2023-01-20 22:30:30")将字符串解析为Time类型,第一个参数是格式。
19 数字解析
strconv包提供了一些用于转化数字和字符串的函数
strconv.Parseint("111", 10, 64)将字符串转化为int类型,第二个参数为进制数,第三个参数为返回值位数,返回值类型为(int64, error)
strconv.ParseFloat("3.14", 64)解析浮点数,返回(Float64, error)
strconv.Atoi("123")string转int,返回(int, error)
20 进程信息
os.Args获取命令行参数
os.Getenv("PATH")获取环境变量
exec.Command("grep", "127.0.0.1", "/etc/hosts")在终端执行命令
引用参考
- 《Go程序设计语言》
- github.com/wangkechun/…