go语言的net/http包的基础使用

写一个能发声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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值