• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Go语言专题

武飞扬头像
赵宗义11
帮助1

1. 轻量级线程goroutine和互斥锁的用法

以下代码展示了goroutine的最基本的用法:

package main

func foo() {
	n := 1
	for {
		println("foo:", n)
		n  = 1
		if n > 2 {
			break
		}
	}
}

func bar() {
	n := 1
	for {
		println("bar:", n)
		n  = 1
		if n > 2 {
			break
		}
	}
}


func main() {
	go foo()
	go bar()
	println("Finish!")
}
学新通

该代码将foo()和bar()这两个函数当做独立的线程来运行,但是当我们运行该代码的时候没有得到这两个线程的任何输出,如下图所示:
学新通
这是因为在这两个线程开始运行之前,主程序就已经运行结束了。为了令这两个线程能够正常运行,我们需要增加一个WaitGroup。修改后的程序如下图所示:

package main
import (
		"sync"
		)

var wg sync.WaitGroup

func foo() {
	defer wg.Done()
	n := 1
	for {
		println("foo:", n)
		n  = 1
		if n > 2 {
			break
		}
	}
}

func bar() {
	defer wg.Done()
	n := 1
	for {
		println("bar:", n)
		n  = 1
		if n > 2 {
			break
		}
	}
}


func main() {
	wg.Add(2)
	go foo()
	go bar()
	wg.Wait()
	println("Finish!")
}
学新通

通过增加WaitGroup,我们可以使得这两个线程被正常执行,如下图所示:
学新通
但是这样的话,当两个线程访问同一资源的时候,它们之间就可能会发生竞争,从而导致程序的运行结果不正确。比如,考虑如下程序:

package main
import (
		"sync"
		)

var wg sync.WaitGroup
var counter int

func foo() {
	defer wg.Done()
	n := 1
	for {
		counter  = 1
		n  = 1
		if n > 10000 {
			break
		}
	}
}

func bar() {
	defer wg.Done()
	n := 1
	for {
		counter  = 1
		n  = 1
		if n > 10000 {
			break
		}
	}
}


func main() {
	counter = 0
	wg.Add(2)
	go foo()
	go bar()
	wg.Wait()
	println("counter:", counter)
}
学新通

该程序的执行结果如下:
学新通
在这个程序中,我们预期的输出应该是counter=20000,但是因为foo()和bar()这两个函数之间发生了竞争,所以程序每次运行其结果都可能会发生变化。为了解决这个问题,我们可以给资源counter加一个互斥锁。修改后的代码如下所示:

package main
import (
		"sync"
		)

var wg sync.WaitGroup
var counter int
var m sync.Mutex

func foo() {
	defer wg.Done()
	n := 1
	for {
		m.Lock()
		counter  = 1
		m.Unlock()
		n  = 1
		if n > 10000 {
			break
		}
	}
}

func bar() {
	defer wg.Done()
	n := 1
	for {
		m.Lock()
		counter  = 1
		m.Unlock()
		n  = 1
		if n > 10000 {
			break
		}
	}
}


func main() {
	counter = 0
	wg.Add(2)
	go foo()
	go bar()
	wg.Wait()
	println("counter:", counter)
}
学新通

以上程序执行结果如下:
学新通

2. 定义一个数组,之后将其容量增加1

首先我们可以使用如下程序定义一个容量为10的int型数组:

package main

func main() {
	b := make([]int, 10)
	for i := 0; i < len(b); i  = 1 {
		b[i] = i*i
	}
	println("len:", len(b))
	for i := 0; i < len(b); i  = 1 {
		println(i, b[i])
	}
}

其执行结果如下:
学新通
现在我们增加以下语句:

b = append(b, make([]int, 1)...)

增加该语句后的程序如下:

package main

func main() {
	b := make([]int, 10)
	for i := 0; i < len(b); i  = 1 {
		b[i] = i*i
	}
	println("original:")
	println("len:", len(b))
	for i := 0; i < len(b); i  = 1 {
		println(i, b[i])
	}
	println("new:")
	b = append(b, make([]int, 1)...)
	println("len:", len(b))
	for i := 0; i < len(b); i  = 1 {
		println(i, b[i])
	}
}
学新通

其执行结果如下:
学新通
注意,这里我们增加的语句是b = append(b, make([]int, 1)...)而不是b = append(b, make([]int, 1)),这里的...的具体含义目前尚不清楚。

3. dial tcp 172.217.160.113:443: i/o timeout

在我的程序中如下一段代码:

import (
	"math"
	"runtime"
	"sync/atomic"
	"time"

	"github.com/go-kratos/aegis/pkg/cpu"
	"github.com/go-kratos/aegis/pkg/window"
	"github.com/go-kratos/aegis/ratelimit"
)

在运行的过程中会提示以下错误:

bbr/bbr.go:9:2: github.com/fsnotify/fsnotify@v1.5.1: Get "https://proxy.golang.org/github.com/fsnotify/fsnotify/@v/v1.5.1.mod": dial tcp 172.217.160.113:443: i/o timeout
bbr/bbr.go:10:2: github.com/fsnotify/fsnotify@v1.5.1: Get "https://proxy.golang.org/github.com/fsnotify/fsnotify/@v/v1.5.1.mod": dial tcp 172.217.160.113:443: i/o timeout
bbr/bbr.go:11:2: github.com/fsnotify/fsnotify@v1.5.1: Get "https://proxy.golang.org/github.com/fsnotify/fsnotify/@v/v1.5.1.mod": dial tcp 172.217.160.113:443: i/o timeout

解决这个问题的方案是在命令行执行以下命令:

go env -w GOPROXY=https://goproxy.cn

之后再次运行该程序就不会提示这个错误了。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfbbjj
系列文章
更多 icon
同类精品
更多 icon
继续加载