context finished but not practice

main
Your Name 2024-07-29 00:25:13 +08:00
parent f8dda033a4
commit 1b56fec40f
8 changed files with 287 additions and 0 deletions

43
context/context-why.go Normal file
View File

@ -0,0 +1,43 @@
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
//var notify bool
//var exitChan chan bool = make(chan bool, 1)
// why context
func f() {
defer wg.Done()
//loop:
for {
fmt.Println("hello world")
time.Sleep(time.Millisecond * 500)
//if notify {
// break
//} //变量
//select {
//case <-exitChan:
// break loop
//default:
//} //channel 版本
}
}
func main() {
wg.Add(1)
go f()
time.Sleep(time.Second * 3)
//如何通知goroutine退出
//exitChan <- true
wg.Wait()
}

View File

@ -0,0 +1,34 @@
package main
import (
"context"
"fmt"
)
func gen(ctx context.Context) <-chan int {
dst := make(chan int)
n := 1
go func() {
for {
select {
case <-ctx.Done():
return // return结束该goroutine防止泄露
case dst <- n:
n++
}
}
}()
return dst
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 当我们取完需要的整数后调用cancel
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
}

View File

@ -0,0 +1,23 @@
package main
import (
"context"
"fmt"
"time"
)
func main() {
d := time.Now().Add(2000 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), d)
// 尽管ctx会过期但在任何情况下调用它的cancel函数都是很好的实践。
// 如果不这样做,可能会使上下文及其父类存活的时间超过必要的时间。
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}

View File

@ -0,0 +1,39 @@
package main
import (
"context"
"fmt"
"sync"
"time"
)
// context.WithTimeout
var Wg sync.WaitGroup
func worker(ctx context.Context) {
LOOP:
for {
fmt.Println("db connecting ...")
time.Sleep(time.Millisecond * 10) // 假设正常连接数据库耗时10毫秒
select {
case <-ctx.Done(): // 50毫秒后自动调用
break LOOP
default:
}
}
fmt.Println("worker done!")
Wg.Done()
}
func main() {
// 设置一个50毫秒的超时
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
Wg.Add(1)
go worker(ctx)
time.Sleep(time.Second * 5)
cancel() // 通知子goroutine结束
Wg.Wait()
fmt.Println("over")
}

View File

@ -0,0 +1,48 @@
package main
import (
"context"
"fmt"
"sync"
"time"
)
// context.WithValue
type TraceCode string
var wait sync.WaitGroup
func workerProc(ctx context.Context) {
key := TraceCode("TRACE_CODE")
traceCode, ok := ctx.Value(key).(string) // 在子goroutine中获取trace code
if !ok {
fmt.Println("invalid trace code")
}
LOOP:
for {
fmt.Printf("worker, trace code:%s\n", traceCode)
time.Sleep(time.Millisecond * 10) // 假设正常连接数据库耗时10毫秒
select {
case <-ctx.Done(): // 50毫秒后自动调用
break LOOP
default:
}
}
fmt.Println("worker done!")
wait.Done()
}
func main() {
// 设置一个50毫秒的超时
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
// 在系统的入口中设置trace code传递给后续启动的goroutine实现日志数据聚合
ctx = context.WithValue(ctx, TraceCode("TRACE_CODE"), "12512312234")
wait.Add(1)
go workerProc(ctx)
time.Sleep(time.Second * 5)
cancel() // 通知子goroutine结束
wait.Wait()
fmt.Println("over")
}

52
context/context.go Normal file
View File

@ -0,0 +1,52 @@
package main
import (
"context"
"fmt"
"sync"
"time"
)
var WG sync.WaitGroup
func f1(ctx context.Context) {
defer WG.Done()
go f2(ctx)
loop:
for {
fmt.Println("hello world")
time.Sleep(time.Millisecond * 500)
select {
case <-ctx.Done():
break loop
default:
}
}
}
func f2(ctx context.Context) {
defer WG.Done()
loop:
for {
fmt.Println("hello wangao")
time.Sleep(time.Millisecond * 500)
select {
case <-ctx.Done():
break loop
default:
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
WG.Add(1)
go f1(ctx)
time.Sleep(time.Second * 3)
//如何通知goroutine退出
cancel()
WG.Wait()
}

1
context/context.log Normal file
View File

@ -0,0 +1 @@
如何优雅的控制子goroutine退出

47
leetcode/reverseList.go Normal file
View File

@ -0,0 +1,47 @@
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var pre *ListNode
cur := head
for cur != nil {
tmp := cur.Next //暂存初始方向
cur.Next = pre //改变链表方向
pre = cur //移动指针
cur = tmp //移动指针2
}
return pre
}
func main() {
head := &ListNode{
Val: 1,
Next: &ListNode{
Val: 2,
Next: &ListNode{
Val: 3,
Next: &ListNode{
Val: 4,
Next: &ListNode{
Val: 5,
Next: nil,
},
},
},
},
}
fmt.Printf("%#v\n", head)
ret := reverseList(head) //反转之后的头节点
fmt.Printf("%#v\n", ret)
for ret != nil {
fmt.Print(ret.Val, "->")
ret = ret.Next //指针移动,直到链表的尾部
}
}