写一个能发声get请求的http协议的client端
func main() {
resp, err := http.Get("http://www.baidu.com") //使用get方法请求百度主页的内容.
if err != nil {
fmt.Printf("get failed ,err :%v\n", err)
return
}
defer resp.Body.Close() //注意这里使用defer关闭的是resp.body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("read from resp.Body failed,err :%v\n", err)
return
}
fmt.Print(string(body)) //这里要将body内容转换成字符串形式进行显示.
}
返回结果
网页返回的结果.
带参数的get请求实例
var wg sync.WaitGroup
func worker() {
for {
fmt.Println("worker")
time.Sleep(time.Second)
}
wg.Done() //这里是无法退出的.因为进入到worker函数中后执行for循环,循环没又退出的条件.
}
func main() {
wg.Add(1)
go worker()
wg.Wait()
fmt.Println("over")
}
使用全局变量让grouting退出
//全局变量方式
var wg sync.WaitGroup
var exit bool
func worker() {
for {
fmt.Println("worker")
time.Sleep(time.Second)
if exit {
break
}
}
wg.Done()
}
func main() {
wg.Add(1)
go worker()
time.Sleep(time.Second * 3)
exit = true
wg.Wait()
fmt.Println("over")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
worker
worker
worker
over
使用通道方式退出
//通道方式退出
var wg sync.WaitGroup
func worker(exitChan chan bool) {
LOOP:
for {
fmt.Println("sorker")
time.Sleep(time.Second)
select {
case <-exitChan:
break LOOP
default:
}
}
wg.Done()
}
func main() {
var exitChan = make(chan bool)
wg.Add(1)
go worker(exitChan)
time.Sleep(time.Second * 3)
exitChan <- true
close(exitChan)
wg.Wait()
fmt.Println("over")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
sorker
sorker
sorker
over
说明一下.这里使用的是channel方式进行退出操作.
将groutine中预先设置传参类型为channel类型,==>在main中将制定的值传入到channel中,==>channel中的数据在groutine中就成了一个触发点.只要满足channel的触发条件就可以退出groutine.
使用官方推荐的版本退出groutine
//官方版本退出groutine
var wg sync.WaitGroup
func worker1(ctx context.Context) {
LOOP:
for {
fmt.Println("worker1")
time.Sleep(time.Second)
select {
case <-ctx.Done(): //将触发结束标志.结束当前循环.跳出LOOP循环体.
break LOOP
default:
}
}
wg.Done() //减少计数.为主函数中的
}
func worker2(ctx context.Context) {
LOOP:
for {
fmt.Println("worker2")
time.Sleep(time.Second)
select {
case <-ctx.Done():
break LOOP
default:
}
}
wg.Done()
}
func main() {
ctx, cancel := context.WithCancel(context.Background()) //声明ctx参数+方法,和cancel结束标志,在后面的groutine的时候调用.
wg.Add(2)
go worker1(ctx)
go worker2(ctx)
time.Sleep(time.Second * 3)
cancel() //一个结束信号,向goroutine中专递一个参数.让groutine出发结束标志.
wg.Wait() //统计groutine数量全部结束.并向下执行其他语句.(如果没有的话也可以向下执行其他语句,但是不能保证groutine全部关闭.
fmt.Println("over")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
worker1
worker2
worker2
worker1
worker1
worker2
worker1
worker2
over
func gen(ctx context.Context) chan int {
dst := make(chan int)
n := 1
go func() {
for {
select {
case <-ctx.Done():
return
case dst <- n:
n++
default:
}
}
}()
return dst
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel() //结束goroutine
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
1
2
3
4
5
上面的示例代码中,
gen
函数在单独的goroutine中生成整数并将它们发送到返回的通道。 gen的调用者在使用生成的整数之后需要取消上下文,以免gen
启动的内部goroutine发生泄漏。
使用预设值的超时时间进行groutine的退出
var wg sync.WaitGroup
func worker(ctx context.Context) {
LOOP:
for {
select {
case <-ctx.Done(): //50毫秒后自动调用.
break LOOP
default: //将默认的操作放到default中进行操作更容易理解一些.
fmt.Println("db connecting ...")
time.Sleep(time.Millisecond * 10) //假设正常连接数据库耗时10毫秒
}
}
fmt.Println("worker done")
wg.Done()
}
func main() {
//设置一个50毫秒的超时时间,一单时间到了就会自动调用groutine中的ctx.done()用来结束groutine
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
wg.Add(1)
go worker(ctx)
time.Sleep(time.Second * 5)
cancel() //通知子groutine结束
wg.Wait()
fmt.Println("Over")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
db connecting ...
db connecting ...
db connecting ...
db connecting ...
db connecting ...
worker done
Over
waitValue
type TranceCode string
var wg sync.WaitGroup
func worker(ctx context.Context) {
key := TranceCode("Trance_CODE")
tranceCode, ok := ctx.Value(key).(string) //在groutine中获取trace code
if !ok {
fmt.Println("invalid trace code")
}
LOOP:
for {
select {
case <-ctx.Done():
break LOOP
default:
fmt.Printf("worker,trace code %s\n", tranceCode)
time.Sleep(time.Millisecond * 10)
}
}
fmt.Println("worker done!")
wg.Done()
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50) //这里传入的貌似是一个时间段用来设定超时时间.
// 到了时间之后就将一个结束参数传入到goroutine中.
ctx = context.WithValue(ctx, TranceCode("Trace_CODE"), "123445324234")
wg.Add(1)
go worker(ctx)
time.Sleep(time.Second * 5)
cancel()
wg.Wait()
fmt.Println("over")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\fuwud>fuwud.exe
invalid trace code
worker,trace code
worker,trace code
worker,trace code
worker,trace code
worker,trace code
worker done!
over