go常用模型

本文介绍了Go语言中的模块管理工具如gomod、GOPROXY配置,以及如何使用context管理并发任务、取消任务,还涉及单元测试和goroutine的生命周期管理。
摘要由CSDN通过智能技术生成

环境

国内使用代理
GOPROXY=“https://goproxy.io,direct”

开启mod
set GO111MODULE=on //windows
export GO111MODULE=on //linux
常用命令

go mod init  # 初始化go.mod
go mod tidy  # 更新依赖文件
go mod download  # 下载依赖文件
go mod vendor  # 执行此命令,会将刚才下载至 GOPATH 下的依赖复制至该项目根目录下的 vendor(自动新建) 文件夹下

go mod edit  # 手动修改依赖文件
go mod graph  # 打印依赖图
go mod verify  # 校验依赖


启动携程池消费任务模型

package main

import (
	"fmt"
	_ "net/http/pprof"
	"runtime"
	"sync"
)

var wg = sync.WaitGroup{}

func busi(ch chan int) {

	for t := range ch {
		fmt.Println("go task = ", t, ", goroutine count = ", runtime.NumGoroutine())
		wg.Done()
	}
}

func sendTask(task int, ch chan int) {
	wg.Add(1)
	ch <- task
}

func main() {

	ch := make(chan int)   //无buffer channel

	goCnt := 2              //启动goroutine的数量
	for i := 0; i < goCnt; i++ {
		//启动go
		go busi(ch)
	}

	taskCnt := 10 //模拟用户需求业务的数量
	for t := 0; t < taskCnt; t++ {
		//发送任务
		sendTask(t, ch)
	}

	wg.Wait()
	select {

	}
}

context与取消任务

package main

import (
	"context"
	"fmt"
	_ "net/http/pprof"
	"runtime"
	"sync"
	"time"
)

var wg = sync.WaitGroup{}

func isCanceled(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(i int, ctx context.Context) {
			defer wg.Done()
			for {
				if isCanceled(ctx) {
					break
				}
				time.Sleep(time.Millisecond * 10)
			}
			fmt.Printf("task %d is canceled\n", i)
		}(i, ctx)
	}

	fmt.Println("goroutine count = ", runtime.NumGoroutine())
	cancel()
	wg.Wait()
}

单元测试相关

文件名:对应测试函数文件名+“_test”
函数:Test开头

package testing

import (
	"bytes"
	"strings"
	"testing"
)

// 命令行执行 go test -v -cover
func TestSquare(t *testing.T) {
	input := [...]int{1, 2, 3}
	expected := [...]int{1, 4, 9}

	for i := 0; i < len(input); i++ {
		ret := square(input[i])
		t.Logf("%d %d", ret, expected[i])
	}
}

// 	命令行执行 go test -bench=. -benchmem
func BenchmarkContactStringByAdd(b *testing.B) {

	b.ResetTimer()
	s := ""
	for i := 0; i < 100; i++ {
		s += "a "
	}

	b.StopTimer()
}

func BenchmarkContactStringByBytesBuff(b *testing.B) {

	b.ResetTimer()
	var buf bytes.Buffer
	for i := 0; i < 100; i++ {
		buf.WriteString("a ")
	}

	b.StopTimer()
}

func BenchmarkContactStringByStringBuff(b *testing.B) {

	b.ResetTimer()
	var buf strings.Builder
	for i := 0; i < 100; i++ {
		buf.WriteString("a ")
	}

	b.StopTimer()
}

go携程捕获异常方式

func Go(x func())  {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				fmt.Println(err)
			}
		}()
		x()
	}()
}

goroutine生命周期管理

  • 并发行为交给调用者
  • 管控goroutine生命周期,知道什么时候退出
  • 可控制goroutine退出
package main

import (
	"context"
	"fmt"
	"time"
)

type Tracker struct {
	ch   chan string
	stop chan struct{}
}

func NewTracker() *Tracker {
	return &Tracker{
		ch:   make(chan string, 10),
		stop: make(chan struct{}),
	}
}

func (t *Tracker) Event(ctx context.Context, data string) error {
	select {
	case t.ch <- data:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func (t *Tracker) Run() {
	for data := range t.ch {
		fmt.Println(data)
		time.Sleep(10 * time.Second)

	}
	t.stop <- struct{}{}
}
// 退出
func (t *Tracker) Shutdown(ctx context.Context) {
	close(t.ch)
	select {
	case <-t.stop:
		fmt.Println("shutdown", "task finish")
	case _ = <-ctx.Done():
		fmt.Println("shutdown", "timeout")
	}
}

func main() {
	start := time.Now().Second()

	tr := NewTracker()
	go tr.Run()
	_ = tr.Event(context.Background(), "tess")
	_ = tr.Event(context.Background(), "test")
	_ = tr.Event(context.Background(), "test")
	_ = tr.Event(context.Background(), "test")
	_ = tr.Event(context.Background(), "test")
	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second))

	defer func() {
		cancel()
		cost := time.Now().Second() - start
		fmt.Println("main cost:", cost)
	}()

	tr.Shutdown(ctx)

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值