环境
国内使用代理
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)
}