Go语言基础
优势
- 高性能、高并发
- 语法简单、学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收(和Java一样)
字节使用Go的原因
- 最初使用Python,由于性能差换成了Go
- C++不适合在线的Web业务
- Java在早期团队的普及率不高
- GO性能更好
- 部署简单、学习成本低
- 内部RPC和HTTP框架的推广
安装与配置环境
- go.dev 官网下载go1.20.4.windows-amd64.msi安装
2.配置环境变量
3.安装完毕
4.安装ide,安装VScode的go插件
变量
func main() {
name := "Go Developers"
var a, b, c int = 1, 2, 3 //var 变量名称 变量类型
//d := true //;=快速定义
//e := "hello" + "world" //+表示连接
}
选择结构
var username string
var sno int
fmt.Scanln(&username, &sno)
switch username {
case "hjq":
if sno == 1 { //大括号必须同行,而且必有不能单行省略
fmt.Println(username, " certificate accepted")
} else {
fmt.Println("warring...Unauthorized")
}
case "hhq":
if sno != 1 {
fmt.Println(username, " certificate accepted")
} else if sno == 1 {
fmt.Println("warring...Unauthorized")
}
default:
fmt.Println("attack!")
break
}
The if...else if...else Statement
if语句可以后接一个可选的else if...else语句,这种类型的结构可以很方便的用来对多个条件进行测试。
使用此结构,需要注意以下几个方面
if语句后可以不接else语句,或者接一个else语句,并且else语句只能跟在else if语句后面。
if语句可以接零个,或多个else if语句,else if语句必须在else语句前面。
一旦匹配上else if语句,剩余的条件将不会验证。
循环结构
func main() {
i := 1
for { //只支持for循环
fmt.Println("loop")
break
}
for j := 1; j < 5; j = j + 2 {
if j == 1 {
continue
}
fmt.Println(j)
}
for i <= 3 {
fmt.Println(i)
i++
}
}
与多数语言不同的是,Go语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构,关键字 for 的基本使用方法与C/C++中非常接近:
使用循环语句时,需要注意的有以下几点:
- 左花括号
{必须与 for 处于同一行。 - Go语言中的 for 循环与C语言一样,都允许在循环条件中定义和初始化变量,唯一的区别是,Go语言不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量。
- Go语言的 for 循环同样支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪一个循环
切片
package main
import (
"fmt"
)
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[0], "len:", len(s))
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) //a b c d e f
//切片
fmt.Println(c[2:5]) //2到5不包括5
fmt.Println(c[:5]) //省略从头
fmt.Println(c[:])
exercise := []string{"h", "i", "g", "h", "s"}
fmt.Println(exercise)
exercise3 := []string{"h", "i", "gs", "hsa", "s"}
fmt.Println(exercise3)
//映射
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m, len(m), m["one"], m["unknown"])
r, ok := m["unknown"]
fmt.Println(r, ok)
m2 := map[string]int{"mon": 1, "tue": 2, "wen": 3}
fmt.Println(m2)
}
切片是围绕着动态数组的概念来构建的,它跟数组类似,是用于管理数据集合的一种数据结构。
数组一旦创建就不能更改其长度和类型,而切片就不同,切片可以按需自动增长和缩小,增长一般使用内置的 append 函数来实现,而缩小则是通过对切片再次进行切割来实现。
切片内部实现
切片对底层数组进行了抽象,并提供相关的操作方法,其内部包含3个字段:指向底层数组的指针、切片访问的元素的个数(即长度)、切片运行增长到的元素个数(即容量)。
切片的创建有两种方式:一种是使用 make 函数来创建,另一种是使用字面量方式创建。
range
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
Println("index", i, "num", num)
}
Println(sum)
m3 := map[string]string{"a": "A", "b": "B"}
for k, v := range m3 {
Println(k, v)
}
for k := range m3 {
Println("key", k)
}
函数与指针
func add1(n int) {
n += 2
}
func add2(n *int) {
*n += 2
}
func main() {
Println(add(1, 2))
v, ok := exists(map[string]string{"a": "A", "b": "B"}, "a")
Println(v, ok)
N := 2
add1(N)
Println(N) //没改变
add2(&N)
Println(N)
}
指针在Go语言中可以被拆分为两个核心概念:
-
类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
-
切片,由指向起始元素的原始指针、元素数量和容量组成。
受益于这样的约束和拆分,Go语言的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移,从而避免了非法修改关键性数据的问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。
结构
type user struct {
name string
password string
}
func main() {
a := user{name: "hjq", password: "5050"}
b := user{"hhq", "8080"}
b.resetPassword("8089")
Println(checkPassword(&b, "8080"))
Println(a, b)
}
func checkPassword(u *user, password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
go的结构使用很灵活,在定义时的代码量就大大降低,灵活使用可以大大降低了定义的成本,可以将结构体作为参数,调用结构体中的成员变量进行操作,类似类的成员变量。