golang中的内存泄露主要有以下几种场景:
下面是一个简单的代码示例,展示了如何避免golang中的内存泄露:
package main
import (
"bytes"
"context"
"fmt"
"sync"
"time"
)
func main() {
// 字符串和切片的正确使用
s := "hello world"
b := []byte(s)
// 使用copy函数创建新的切片
b1 := make([]byte, len(b))
copy(b1, b)
// 使用bytes.Buffer类型创建新的字符串
var buf bytes.Buffer
buf.Write(b)
s1 := buf.String()
fmt.Println(s, s1)
// goroutine的正确使用
var wg sync.WaitGroup
// 使用互斥锁访问共享资源
var mu sync.Mutex
counter := 0
wg.Add(10)
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(counter)
// 使用有缓冲或者关闭的通道进行数据交换
ch := make(chan int, 10)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
ch <- i
}(i)
}
go func() {
wg.Wait()
close(ch) // 关闭通道
}()
for n := range ch {
fmt.Println(n)
}
// 使用超时或者取消机制终止goroutine
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) // 创建一个带有超时的上下文对象
defer cancel()
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case <-ctx.Done(): // 检查上下文对象的状态
fmt.Println("goroutine exit")
return
default:
fmt.Println("goroutine running")
time.Sleep(time.Second)
}
}
}()
wg.Wait()
// 定时器的正确使用
ticker := time.NewTicker(time.Second) // 创建一个定时器
wg.Add(1)
go func() {
defer wg.Done()
for t := range ticker.C { // 接收定时器的信号
fmt.Println("ticker triggered", t)
if t.After(time.Now().Add(5 * time.Second)) { // 设置一个退出条件
ticker.Stop() // 停止定时器
fmt.Println("ticker stopped")
return
}
}
}()
wg.Wait()
}