Go语言学习笔记03--流程控制循环语句与函数 - Go语言中文社区

Go语言学习笔记03--流程控制循环语句与函数


1.三目运算符
    特别注意!在go语言中不存在三目运算符这个东西!
    不是不推荐使用,就是完全不存在!

2.循环结构
    go语言中有且仅有一种循环结构,就是for循环结构。不存在while或者dowhile这样的循环结构。
        for 表达式1;表达式2;表达式3{
            循环体
        }
    循环的结构与标识符含义几乎与传统c语言相同。
    (1)表达式1:循环变量赋初值
    (2)表达式2:循环能够继续的循环条件
    (3)表达式3:循环变量向着循环结束的方向变化
    eg:
        for num:=0; num<10; num++{
            fmt.Println(num);
        }
    注意:go语言中的变量作用域为块级作用域,而不是函数级作用域!
          因此定义在for循环内部的变量,其作用域仅能够在for循环内部生效,
          因此它们在for循环之外是不能够被访问的!千万注意!
          eg:
                  {
                      num:=100;
                  }
                  fmt.Println(num);//违法!
    注意:go语言中的for循环结构也最好不要写成拆分形式
          num:=0;
          for ;num<10;num++{
              ...
          }
          可能会导致循环变量未能正确被赋初值的问题(原因还是go语言的块级作用域)
    了解:break辅助流程控制语句
          break语句的作用是用来立即结束循环,break语句后面的内容不再被执行。
    注明:在go语言中允许for后不写任何内容,而是直接写出大括号与循环体。
          但是这种写法其实是死循环的一种表现形式,类似于for(;;){..}这种。
          正常来讲如果使用这种写法需要在循环体内添加break保证循环能够终止。
          eg:
                  for{
                      fmt.Println("hello world!");
                      break;
                  }
3.辅助控制
    go语言中流程控制的辅助语句和c语言中大同小异
        break、continue、goto

    break:跳出所在层循环,当前循环结束
    continue:跳出所在层循环的本次循环,当前循环不结束
    goto:跳转到指定标志位置

4.函数
    在go语言中函数由关键词func指定,函数结构如下所示
    语法:
        func 函数名(参数1 参数1数据类型, 参数2 参数2数据类型, ...){
            函数体
        }
    eg:
        func getSum(num1 int, num2 int){
            fmt.Println(num1+num2);
        }
    (1)特别需要注意,在go语言中函数的参数必须指定参数数据类型!
        //下面的写法就是一个违法操作!
        func getSum(num1, num2){
            ...
        }
    (2)对于go语言而言,由于函数是不能定义在main函数之内的,因此不存在类似JS中函数提升的问题
        但是必须了然一件事情那就是函数必须声明之后才能调用。
        func getSum(num1 int, num2 int){
            fmt.Println(num1+num2);
        }
        func main(){
            //而且形参与实参的数据类型也必须相同
            getSum(100,200);
        }
    (3)但是函数参数的【值传递】与【引用传递】问题仍然存在,因此需要注意。
        func swap(num1 int, num2 int){
            temp := num1;
            num1 = num2;
            num2 = temp;
        }
        func main(){
            var temp1 int = 100;
            var temp2 int = 80;
            //赋值传递!
            swap(temp1, temp2);
            fmt.Println(temp1);//100
            fmt.Println(temp1);//80
        }
    (4)函数的不定参列表
        go语言中允许声明不定参函数,其声明语法采用...三点符号来实现
            func 函数名(args ...数据类型){...}
        其中args只是一个随意书写的形参名称,与形参本身并无任何影响(本质上是一个数组结构)
        eg:
            func getParas(args ...int){
                fmt.Printf("%T",args);//[] int
            }
    (5)for循环的快速遍历在函数中的作用
        对于for循环而言,可以通过range关键字,对复杂数据类型进行快速遍历
        以不定参函数为例:
            func getParas(args ...int){
                for index,val := range args{
                    fmt.Printf("%d,%dn",index,val);
                }
            }
        本操作类似于传统c语言或js语言中的for in快速遍历模式。
        而如果在快速遍历中,有参数不需要书写,则可以通过匿名变量来进行赋值的隐藏。
            func getParas(args ...int){
                for _,val := range args{
                    fmt.Printf("%dn",val);
                }
            }
    (6)在go语言中,所有的函数都是全局函数,可以被项目中的所有文件使用。
        不必出现import这种类似导入的操作
        这也就意味着出现了一个非常重要的问题,那就是所有的函数名都是唯一的!不能重复!
    (7)不定参函数的嵌套使用
        函数的不定参传递与普通的参数传递语法并不相同
            func func1(args1 ...int){...}
            func func2(args2 ...int){
                //这样的操作是违法的,因为args2是int[]类型,而args1则约定了函数需要int类型
                //func1(args2);

                //正确的做法应当是使用下面的做法,将args2的部分参数传递到func1中
                func1(args2[beginindex:endIndex] ...);
            }
        而这种写法带来了一些特殊的注意事项:
            1)beginIndex和endIndex都是可写可不写,但都表示到哪一个下标为止(不包括这个元素)
            2)endIndex如果小于实际传入的参数个数,则正常加载
            3)endIndex若大于实际传入的参数个数,则出现下标越界的错误!
            eg:
                func getParas(args ...int){
                    for index,value := range args{
                        fmt.Printf("%d,%dn",index,value);
                    }
                }
                func getParas1(args ...int){
                    getParas(args[:]...);
                }
    (8)函数的返回值
        go语言中函数的返回值可以说和所有的传统编程语言都有所不同。虽然也体现在return关键词上,
        但是返回值的语法结构却截然不同。
            func 函数名() 返回值类型{
                return 返回值;
            }
        在函数声明的时候,如果函数存在有返回值,则必须在函数声明的位置指明函数的返回值数据类型
        而后在函数内部的函数体重,return后的返回值也必须是这个类型的内容(数据或表达式均可)。
            func getSum(num1 int, num2 int) int{
                return num1+num2;
            }
        注意事项:
            1)如果函数声明中不存在有返回值类型的说明,那么在函数体内使用关键词return就是违法的操作
                eg:
                    func getSum(num1 int, num2 int){
                        return num1+num2;
                    }
            2)return关键词除了有返回值的含义之外,还具有停止函数的作用。
              即return关键词后的语句不再会得到执行。
                  eg:
                      func getSum(num1 int, num2 int) int{
                        return num1+num2;
                        fmt.Println("sentence1");//不执行
                        fmt.Println("sentence2");//不执行
                        ...                         //不执行
                    }
            3)另外返回值的语法也可以采用【预先声明】的写法,来保证先分配内存空间的目的。
              在预先声明的写法中,return关键词之后就不再需要主动写明任何内容。
                eg:
                    func getSum(num1 int, num2 int)(sum int){
                        sum = num1 + num2;
                        return;
                    }
        --------------------------------------------------------------------------------------------------------------------
        |特别注意:                                                                                                                         |
        |    在go语言中是允许函数存在多个返回值的,并且多个返回值必须采用预先声明写法     |
        |    eg:                                                                                                                               |
        |        func getReturns()(reValue1 int, reValue2 int){                                                           |
        |            reValue1 = ......;                                                                                                     |
        |            reValue2 = ......;                                                                                                     |
        |            return;                                                                                                                    |
        |        }                                                                                                                                 |
        |        func main(){                                                                                                               |
        |            num1,num2 := getReturns();                                                                                 |
        |           fmt.Printf("%d, %d",num1, num2);                                                                         |
        |        }                                                                                                                                 |
        --------------------------------------------------------------------------------------------------------------------

    (9)函数别名(定义函数类型变量,即创建函数指针)
        函数别名是go语言规定,采用关键词type来对函数进行的重命名处理。
        本质上类似于函数指针的获取。只不过函数别名在面向对象思想中表现的比较重要。
        eg:
            func hanshu1(num int){
                fmt.Println(num);
            }
            func hanshu2(num int)int{
                num+=10;
                return num;
            }
            type FUNC_WITHOUT_RETURN_VALUE func (int)
            type FUNC_WITH_RETURN_VALUE func(int) int
            func main() {
                var unparaFunc FUNC_WITHOUT_RETURN_VALUE;
                unparaFunc = hanshu1;
                //上面两句话可以简化为自动推导类型的一句话
                //unparaFunc:=hanshu1;
                unparaFunc(100);

                var paraFunc FUNC_WITH_RETURN_VALUE;
                paraFunc = hanshu2;
                result := paraFunc(100);
                fmt.Println(result);
            }
        而函数指针的获取写法则是下面的表现形式。其实两者对比来看区别不大。
        如果对比自动推导类型的写法,就会发现两者完全一致!
        eg:
            func hanshu1(num int){
                fmt.Println(num);
            }
            func hanshu2(num int)int{
                num+=10;
                return num;
            }
            func main() {
                unparaFunc := hanshu1;
                unparaFunc(100);

                paraFunc := hanshu2;
                result := paraFunc(100);
                fmt.Println(result);
            }
    (10)函数的作用域问题
        因为go语言是一个以{}块来区分作用域的语言,所以严格来讲并不存在什么全局局部的概念。
        但是又因为go语言带有很浓重的c语言风格,因此可以从某种角度上来讲以函数来进行区分。
        所以go语言中的作用域是一个比较复杂的逻辑问题。
            
            全局作用域:go语言认为函数之外的区域,就是全局作用域,
                        全局作用域在程序中永远存在不会消失
              全局变量:go语言认为在全局作用域中声明的变量,就是全局变量,
                         全局变量可以在当前所在文件的任何位置被访问到
              全局常量:go语言认为在全局作用域中声明的常量,就是全局常量,
                         全局常量也可以在当前所在文件的任何位置被访问到

            局部作用域:go语言认为函数之内的区域,就是局部作用域,
                       局部作用域在程序中不会永远存在,会随着函数的生命周期而明灭变化。
              局部变量:go语言认为在局部作用域中声明的变量,就是局部变量,
                         局部变量仅可以在当前所在的函数中被访问到,脱离所在函数即宣告失效。
              局部常量:go语言认为在局部作用域中声明的常量,就是局部常量,
                         局部常量仅可以在当前所在的函数中被访问到,脱离所在函数即宣告失效。

        变量访问原则:【就近原则】
            由于go语言的作用域复杂而繁琐,所以变量在访问时采用就近原则。
            即
                有局部常变量存在前提下,局部常变量生效,
                局部常变量不存在的前提下,上一级局部常变量生效,直至全局常变量为止。
            注意:
                就近原则中的【上一级】,指的是上一个{}大括号范围中。
 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u013792921/article/details/84395320
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-06 22:18:21
  • 阅读 ( 1193 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢