zoukankan      html  css  js  c++  java
  • golang range for循环中如何正确的给goroutine传参

    1.code example

     公共方法

    func testDomain(ii string) {
    	time.Sleep(time.Second * 4)
    	fmt.Printf("pid: %d___point addr: %d___%s 
    ", GoID(), &ii, ii)
    }
    
    func GoID() int {
    	var buf [64]byte
    	n := runtime.Stack(buf[:], false)
    	idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
    	id, err := strconv.Atoi(idField)
    	if err != nil {
    		panic(fmt.Sprintf("cannot get goroutine id: %v", err))
    	}
    	return id
    }
    

      

    2. 错误示范

    var a []string
    for i := 1; i < 5; i++ {
    a = append(a, fmt.Sprintf("%d", i))
    }
    	for _, i := range a {
    		fmt.Printf("-----%s---
    ", i)
    
    		go func() {
    			time.Sleep(time.Second * 4)
    			testDomain(i)
    		}()
    	
    	}
    

     打印发现i每次地址都是同一个

        协助每次先阻塞4秒

      4秒后 i的值是4, 这是协程中的方法testDomain开始工作,将i的值传给自己的形参

    3. 正确示范

    	for _, i := range a {
    		fmt.Printf("-----%s---
    ", i)
    		go func(a string) {
    			//time.Sleep(time.Second * 4)
    			testDomain(a)
    		}(i)
    	}
    

     这种操作会先将i的值传递给形参a,i的变化不会对testDomain方法的执行产生影响

    4. 完整代码

    package main
    
    import (
    	"fmt"
    	"runtime"
    	"strconv"
    	"strings"
    	"time"
    )
    
    func main() {
    	var a []string
    	for i := 1; i < 5; i++ {
    		a = append(a, fmt.Sprintf("%d", i))
    	}
    	for _, i := range a {
    		fmt.Printf("-----%s---
    ", i)
    		go func(a string) {
    			//time.Sleep(time.Second * 4)
    			testDomain(a)
    		}(i)
    
    		go func() {
    			time.Sleep(time.Second * 4)
    			testDomain(i)
    		}()
    		fmt.Println(&i)
    		time.Sleep(time.Second * 1)
    	}
    
    	time.Sleep(100 * time.Second)
    }
    
    func testDomain(ii string) {
    	time.Sleep(time.Second * 4)
    	fmt.Printf("pid: %d___point addr: %d___%s 
    ", GoID(), &ii, ii)
    }
    
    func GoID() int {
    	var buf [64]byte
    	n := runtime.Stack(buf[:], false)
    	idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
    	id, err := strconv.Atoi(idField)
    	if err != nil {
    		panic(fmt.Sprintf("cannot get goroutine id: %v", err))
    	}
    	return id
    }
    

      

      

    没有什么是写一万遍还不会的,如果有那就再写一万遍。
  • 相关阅读:
    常见银行编码收集
    kafka集群在消息消费出现无法找到topic分区的处理解决
    find命令通过排序只保留最新的文件目录
    Git fetch和git pull的区别
    git 常用命令
    wordpress模板修改及函数说明
    webbench进行压力测试
    git存储用户名与密码
    导出putty配置
    一个成功的Git分支模型
  • 原文地址:https://www.cnblogs.com/waken-captain/p/10496454.html
Copyright © 2011-2022 走看看