12-线程同步(go基础)
线程同步在 Go 语言中,经常会遇到并发的问题,当然我们会优先考虑使用通道,同时 Go 语言也给出了传统的解决方式 Mutex(互斥锁) 和 RWMutex(读写锁) 来处理竞争条件。
临界区 首先我们要理解并发编程中临界区的概念。当程序并发地运行时,多个 Go 协程不应该同时访问那些修改共享资源的代码。这些修改共享资源的代码称为临界区 。
12345678910111213141516171819202122232425262728293031323334package mainimport ( "fmt" "sync")type Bank struct { balance int}func (b *Bank) Deposit(amount int) { b.balance += amount}func (b *Bank) Balance() int { return b.balance}func main() { var wg sync.Wa ...
11-Select(go基础)
Selectselect 语句用在多个发送/接收通道操作中进行选择。
select 语句会一直阻塞,直到发送/接收操作准备就绪。
如果有多个通道操作准备完毕, select 会随机地选取其中之一执行。
例子:
程序创建了 3 个通道,并在执行 select 语句之前往通道 1 、通道 2 和 通道 3 分别发送数据,在执行 select 语句时,如果有机会的话会运行所有表达式,只要其中一个通道接收到数据,那么就会执行对应的 case 代码,然后退出。
123456789101112131415161718192021222324252627package mainimport "fmt"func main() { // 创建三个通道 ch1 := make(chan string, 1) ch2 := make(chan string, 1) ch3 := make(chan string, 1) // 往通道发送数据 ch1 <- "111" ch2 <- "222" ch3 <- &qu ...
10-协程和通道(go基础)
协程Go 语言的 协程(Groutine) 是与其他函数或方法一起并发运行的工作方式。协程可以看作是轻量级线程。与线程相比,创建一个协程的成本很小。因此在 Go 应用中,常常会看到会有很多协程并发地运行。
启动一个协程主函数运行在一个特殊的协程上,这个协程称之为 主协程(Main Goroutine) 。
启动一个新的协程时,协程的调用会立即返回。与函数不同,程序控制不会去等待 Go 协程执行完毕。在调用 Go 协程之后,程序控制会立即返回到代码的下一行,忽略该协程的任何返回值。如果 Go 主协程终止,则程序终止,于是其他 Go 协程也会终止。
12345678910111213package mainimport "fmt"func fun() { fmt.Println("另一个协程")}func main() { go fun() fmt.Println("主协程")}
启动多个 Go 协程1234567891011121314151617181920212223242 ...
9-方法和接口(go基础)
方法方法 其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。
方法基础应用123456789101112131415package mainimport "fmt"type myInt intfunc (a myInt) add(b myInt) myInt { return a + b}func main() { var x myInt = 50 var y myInt = 7 fmt.Println(x.add(y)) // 57}
方法在结构体上应用12345678910111213141516171819202122232425262728293031package mainimport "fmt"type Student struct { name string // 学生姓名 sno string // 学生学号}type Teacher s ...
8-流程控制(go基础)
流程控制条件语句123456789if 条件1 { 逻辑代码1} else if 条件2 { 逻辑代码2} else if 条件 ... { 逻辑代码 ...} else { 逻辑代码 else}
选择语句123456789101112switch 表达式 { case 表达式值1: 业务逻辑代码1 case 表达式值2: 业务逻辑代码2 case 表达式值3: 业务逻辑代码3 case 表达式值 ...: 业务逻辑代码 ... default: 业务逻辑代码}
循环语句只有for:四种用法
12345678910111213141516171819// for 接三个表达式for initialisation; condition; post { code}// for 接一个条件表达式for condition { code}/ ...
7-函数(go基础)
函数函数的声明1234567891011121314package mainimport "fmt"//函数返回一个无名变量,返回值列表的括号省略func add(a, b int) int { return a + b}func main() { sum := add(1, 23) fmt.Println(sum)}
可变参数多个类型一致的参数在参数类型前面加 ... 表示一个切片,用来接收调用者传入的参数。注意,如果该函数下有其他类型的参数,这些其他参数必须放在参数列表的前面,切片必须放在最后。
12345678910111213141516package mainimport "fmt"func show(args ...string) int { sum := 0 for _, item := range args { fmt.Println(item) sum += 1 } return sum}func main() { fmt. ...
6-结构体(go基础)
结构体结构体(struct) 是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。学过 C 或 C++ 的人都知道结构体,但在 Go 中,没有像 C++ 中的 class 类的概念,只有 struct 结构体的概念,所以也没有继承。
创建一个结构体123456789101112131415161718192021222324package mainimport "fmt"type Student struct { name string // 学生姓名 sno string // 学生学号 age int // 学生年龄}func main() { stu1 := Student{ name: "jpc", sno: "123456", age: 21, } stu2 := Student{"jzw", "123123", 22} fmt.Println(stu1 ...
5-指针(go基础)
指针指针基础指针也是一种类型,也可以创建变量,称之为指针变量。指针变量的类型为 *Type,该指针指向一个 Type 类型的变量。指针变量最大的特点就是存储的某个实际变量的内存地址,通过记录某个变量的地址,从而间接的操作该变量。
如果指针声明后没有进行初始化,其默认零值是 nil
在函数中对指针参数所做的修改,在函数返回后会保存相应的修改。
Go 中不支持指针运算例如:p++ ,但这在 Go 中是不支持的。
12345func fun() { var num int = 8 var p *int = &num fmt.Println(p)}
指针与切片123456789101112131415161718192021222324252627282930313233package mainimport "fmt"func fun() { num := 8 p := new(int) p = &num fmt.Println(p) fmt.Println(*p)}func fun2(arr []int) ...
4-容器类型(go基础)
容器类型数组数组 是一个由 固定长度 的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。
[3]int 和 [5]int 是不同的类型
123456789101112131415161718192021222324252627282930313233343536373839404142434445package mainimport "fmt"func fun1() { var a [5]int a[1] = 2 fmt.Println(a)}func fun2() { // 二维数组 var a = [5][2]int{{1, 2}, {3, 4}} fmt.Println(a)}func fun3() { // 直接在声明时对数组进行初始化 var arr1 = [5]int{15, 20, 25, 30, 35} fmt.Println(arr1) // 使用短声明 arr2 := [5]int{15, 2 ...
3-基础数据类型(go基础)
基础数据类型Go 语言数据类型包含基础类型和复合类型两大类.
基础数据类型包括:布尔型,整型,浮点型,复数型,字符型,字符串型,错误类型.
复合数据类型包括:指针,数组,切片,字典,通道,结构体,接口.
整形
有符号整型:int8、int16、int32、int64、int。
无符号整型:uint8、uint16、uint32、uint64、uint。
浮点型
float32 的精度只能提供大约 6 个十进制数(表示小数点后 6 位)的精度。
float64 的精度能提供大约 15 个十进制数(表示小数点后 15 位)的精度。
float32的有效bit位只有23个,其它的bit位用于指数和符号;当整数大于23bit能表达的范围时,float32的表示将出现误差.
复数Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度。
1234567var x complex128 = complex(1, 2) // 1+2ivar y complex128 = complex(3, 4) // 3+4if ...