前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言可能会遇到的坑

Go语言可能会遇到的坑

作者头像
我的小碗汤
发布2020-01-13 17:17:41
1K0
发布2020-01-13 17:17:41
举报
文章被收录于专栏:我的小碗汤

点击蓝字关注 ??

阅读本文大约需要3分钟。

最近在用go开发项目的过程中突然发现一个坑,尤其是对于其它传统语言转来的人来说一不注意就掉坑里了,话不多说,咱看代码:

代码语言:javascript
复制
 1//writeToCSV
 2func writeESDateToCSV(totalValues chan []string) {
 3    f, err := os.Create("t_data_from_es.csv")
 4    defer f.Close()
 5    if err != nil {
 6        panic(err)
 7    }
 8
 9    w := csv.NewWriter(f)
10    w.Write(columns)
11
12    for {
13        select {
14        case row := <- totalValues:
15            //fmt.Printf("Write Count:%d log:%s\n",i, row)
16            w.Write(row)
17        case <- isSendEnd:
18            if len(totalValues) == 0 {
19                fmt.Println("------------------Write End-----------------")
20                break
21            }
22        }
23    }
24
25    w.Flush()
26    fmt.Println("-------------------------处理完毕-------------------------")
27    isWriteEnd <- true
28}

当数据发送完毕,即isSendEnd不阻塞,且totalValues里没数据时,跳出for循环,这里用了break。但是调试的时候发现,程序阻塞在了14行,即两个channel都阻塞了。然后才惊觉这里break不是这么玩,然后写了个测试方法测试一下:

代码语言:javascript
复制
package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                break
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }

    fmt.Println("outside the for: ")
}

运行输出如下结果,break now之后还是会继续无限循环,不会跳出for循环,只是跳出了一次select

代码语言:javascript
复制
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
break now
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 

若要break出来,这里需要加一个标签,使用goto, 或者break 到具体的位置。

解决方法一:

使用golang中break的特性,在外层for加一个标签:

代码语言:javascript
复制
package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0

    endLoop:
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                break endLoop
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }

    fmt.Println("outside the for: ")
}

解决方法二:

使用goto直接跳出循环:

代码语言:javascript
复制
package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                goto endLoop
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }
    endLoop:
    fmt.Println("outside the for: ")
}

两程序运行输出如下:

代码语言:javascript
复制
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
break now
outside the for: 

Process finished with exit code 0

综上可以得出:go语言的switch-case和select-case都是不需要break的,但是加上break也只是跳出本次switch或select,并不会跳出for循环。

go、docker、k8s等学习资源,可在文末公众号后台回复【1】加小助手索取

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 进击云原生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档