Go学习笔记
理解指针
指针类型和普通类型区别
package main
import (
"fmt"
)
type User struct {
Id int64
Name string
}
func (user *User) getUserInfo() string {
return fmt.Sprintf("%d %s", user.Id, user.Name)
}
func main() {
n1 := 10
n2 := 20
setValue(n1, &n2)
fmt.Println("n1:", n1, "n2:", n2)
// u1是个对象
u1 := User{
Id: 10,
Name: "tom",
}
println(u1.getUserInfo())
// u2是个指针
u2 := new(User)
u2.Id = 20
u2.Name = "jerry"
println(u2.getUserInfo())
// u3是个指针
u3 := &User{
Id: 30,
Name: "tonny",
}
println(u3.getUserInfo())
println("u1 地址", &u1)
println("u2 指针", u2)
setStruct(u1, u2)
println("---------")
println(u1.getUserInfo())
println(u2.getUserInfo())
println(u3.getUserInfo())
}
func setValue(n1 int, n2 *int) {
n1 += 1
*n2 += 1
}
// user01 传的是对象,相当于把赋值给了这个对象,这个对象和原对象地址不是同一个,任何修改不会影响原对象
// user02 传的是地址,任何修改都会修改原对象
func setStruct(user01 User, user02 *User) {
//user01.Name = "修改user01"
//user02.Name = "修改user02"
println("setStruct user01 地址", &user01)
println("setStruct user02 指针", user02)
updateName(&user01.Name)
updateName(&user02.Name)
}
func updateName(name *string) {
*name = "更新name"
}
指针类型和普通类型初始化
package main
import (
"fmt"
)
type OtherInfo struct {
info *string
info2 string
}
func (otherInfo *OtherInfo) getOtherInfoStr() string {
fmt.Println("执行getOtherInfoStr")
return fmt.Sprint(otherInfo.info, otherInfo.info2)
}
type User struct {
name *string // 指针类型,默认是nil
name2 string // 普通类型,默认是""
otherInfo *OtherInfo // 指针对象,默认nil
otherInfo2 OtherInfo // 普通对象,默认{},相当于new好了一个对象
}
func main() {
user := new(User)
printUser(*user)
str := "名字"
user.name = &str
user.name2 = "名字2"
user.otherInfo = &OtherInfo{info2: "信息"}
user.otherInfo2.info2 = "信息2"
printUser(*user)
}
func printUser(user User) {
fmt.Println("=================")
fmt.Println("user:", user)
fmt.Println("user.name:", user.name)
fmt.Println("user.name2:", user.name2)
fmt.Println("user.otherInfo:", user.otherInfo)
if user.otherInfo != nil {
fmt.Println("user.otherInfo.info:", user.otherInfo.info)
fmt.Println("user.otherInfo.getOtherInfoStr():", user.otherInfo.getOtherInfoStr())
}
fmt.Println("user.otherInfo2:", user.otherInfo2)
fmt.Println("user.otherInfo2.info:", user.otherInfo2.info)
fmt.Println("user.otherInfo2.getOtherInfoStr():", user.otherInfo2.getOtherInfoStr())
}
认识defer、recover、panic关键字
查看代码
package main
import (
"fmt"
)
func main() {
// deferTest()
/**
总结
1、defer延迟执行异常处理
2、recover会捕获抛出的异常(主动异常或未知异常)
3、panic会主动抛出异常
*/
defer exceptionCatch()
panicTest(true)
}
// panic英⽂意思是恐慌,在这⾥意思是抛出⼀个程序异常,即报告程序运⾏时错误
func panicTest(throw bool) {
println("panicTest begin")
if throw {
panic("抛出一个异常")
}
println("panicTest end")
}
// defer有延迟的意思,就是稍后执⾏,先执⾏函数主体内容,defer的内容稍后执⾏
func deferTest() {
// 异常处理 内置函数方式
//defer func() {
// if r := recover(); r != nil {
// fmt.Println("Some error happened!", r)
// ret = -1
// }
//}()
// 异常处理 外部函数方式
defer exceptionCatch()
array := [3]int{2, 3, 4}
index := 0
for ; index < 10; index++ {
println(array[index])
}
}
// recover() 函数⽤于终⽌错误处理流程,也就是我们常规说的 catch
func exceptionCatch() {
if r := recover(); r != nil {
fmt.Println("出现异常了:", r)
}
}
等待所有协程执行完
查看代码
package main
import (
"fmt"
"sync"
"time"
)
// var waitGroup = sync.WaitGroup{} // 这种是主动申请了一个对象
var waitGroup sync.WaitGroup // 这种是默认赋值了一个对象,结果一样
var waitGroup2 sync.WaitGroup
func main() {
run01()
run02()
fmt.Println("主协程执行结束")
}
func run01() {
waitGroup.Add(2)
go func() {
time.Sleep(time.Second)
fmt.Println("执行协程A")
waitGroup.Done()
}()
go func() {
time.Sleep(time.Second)
fmt.Println("执行协程B")
waitGroup.Done()
}()
// 等待所有协程执行完毕
waitGroup.Wait()
}
func run02() {
waitGroup2.Add(1)
go func() {
time.Sleep(time.Second)
fmt.Println("执行协程C")
waitGroup2.Done()
}()
// 等待所有协程执行完毕
waitGroup2.Wait()
}
加锁、释放锁
查看代码
package main
import (
"fmt"
"sync"
"time"
)
var count = 10
var waitGroup sync.WaitGroup
var mutex sync.Mutex
func main() {
waitGroup.Add(2)
go run("协程A")
go run("协程B")
waitGroup.Wait()
fmt.Println("主协程执行完成")
}
func run(name string) {
defer waitGroup.Done()
for {
mutex.Lock() // 加锁
if count <= 0 {
mutex.Unlock() // 释放锁
break
} else {
time.Sleep(time.Second)
count--
mutex.Unlock() // 释放锁
}
fmt.Println(name, "count: ", count)
}
}
读写锁使用
查看代码
package main
import (
"fmt"
"sync"
"time"
)
var waitGroup *sync.WaitGroup
var rwMutex *sync.RWMutex
func init() {
// 两种指针对象化方式
waitGroup = &sync.WaitGroup{}
rwMutex = new(sync.RWMutex)
}
func main() {
waitGroup.Add(4)
go read("协程A")
go read("协程B")
go write("协程C")
go write("协程D")
waitGroup.Wait()
fmt.Println("主协程执行完成")
}
// 读-读 之间不互斥
func read(name string) {
defer waitGroup.Done()
fmt.Println(name, "开始读数据,准备加锁")
rwMutex.RLock() // 读锁
fmt.Println(name, "读数据 begin")
time.Sleep(time.Second)
fmt.Println(name, "读数据 end")
rwMutex.RUnlock() // 释放读锁
fmt.Println(name, "读数据结束,释放锁")
}
// 读-写 写-写 之间互斥
func write(name string) {
defer waitGroup.Done()
fmt.Println(name, "开始写数据中,准备加锁")
rwMutex.Lock()
fmt.Println(name, "写数据 begin")
time.Sleep(time.Second)
fmt.Println(name, "写数据 end")
rwMutex.Unlock()
fmt.Println(name, "写数据结束,释放锁")
}
本文来自博客园,作者:wzyy,转载请注明原文链接:https://www.cnblogs.com/wwzyy/p/17309258.html