zoukankan      html  css  js  c++  java
  • Go 学习笔记

      主要记录下 6.824 课程中关于 Go 的学习教程 Online Go tutorial 的内容,同时也作为笔者学习 Go 的笔记。

      

      基本代码规范

      这里主要列举下和传统的 C/C++ 规范不一致的地方:

      语句的末尾不需要使用 ';' 作为语句的结束标记;

      对于函数的定义而言,函数体开始的左括号应与对应函数名在同一行,不允许换行;

      在条件语句,循环语句开始位置可以插入一个初始化语句,该初始化语句在条件/循环判断之前执行,并仅可在条件/循环语句内可见;

      if / for 等语句的条件部分不需要使用 "()" 将条件包围,同时不支持 C/C++ 中使用单条语句从而省略 "{}" 的写法,即执行体必须位于 "{}" 内;

      

      index

      1.变量

      2.控制语句

      3.复合类型

        3.1 struct

        3.2 array

        3.3 slice

        3.4 map

      变量

      使用关键字 var 定义一个或多个变量,使用形如 var x int 的 var + 标识符 + 类型 的方式进行变量定义,多个变量同类型时可以在最后进行统一的类型声明。

        var x int       //定义整形变量 x
        var x, y int    //定义整形变量 x, y

      变量在定义的同时可以进行初始化,当变量定义指定了初始值时,变量的类型被定义为初始值的类型,此时不再需要进行变量类型的声明。

      Go 同时提供了变量定义以及赋值的语法糖,即使用 ':=' 符号,该符号仅可在函数体内部使用,无法在全局作用域使用,表示定义一个变量并对其进行赋值,此时的变量定义不再需要使用 var 关键字。

        k := 3        //函数体内部定义整形变量 k,初始值为 3

      Go 中可使用的基本数据类型如下所示,这里直接参考的 A Tour of Go 的记录。对应的数据类型在未被初始化时,初始值为 0(整形),false(bool型),""(字符串类型)以及 nil(指针/slice/map类型)。在 Go 中指针类型不支持算数运算,其他操作与 C 中基本一致。

        bool
        string
        int  int8  int16  int32  int64
        uint uint8 uint16 uint32 uint64 uintptr
        byte             // 与 uint8 相同
        rune             // 与 int32 相同,represents a Unicode code point?
        float32 float64
        complex64 complex128   // 复数类型
        *T                       // 指针类型

      多个不同类型的变量的定义可以通过 var() 的形式进行联合定义。

        var(
         x int
         y bool = false
         z float32 = 3.14     //使用 var() 联合定义多个变量
      )

       在 Go 中,不同类型的变量需要使用强制类型转换进行类型转换(貌似常量是不能强制类型转换的)。 Go 中强制类型转换的操作为 type() 的形式。下列示例表示从 double 到 int 类型的转换

        var x float32 = 3.14
        var y int = int(x)            // double 类型强制类型转换为 int

      Go 中的常量使用 const 关键字定义,常量需要在定义时给出初始值,后续无法修改,故而定义时不需要额外说明类型,同时常量定义无法使用 ':=' 操作符定义。

        const a, b = "a", false        //定义常量 a 和 b

       

      控制语句

      循环

      Go 中仅存在 for 循环语句,其控制语句中包含有 "初始化;控制条件;循环后操作" 三个部分。上述这三个部分均为可选项。若想在初始化部分定义变量,则必须使用 ":=" 操作符,且定义的变量仅在 for 循环内部可见。与其他语言不同的是 Go 的循环语句不需要使用 "()" 包括 for 的控制语句,同时循环语句块必须位于 "{}" 中。

        for i := 1; i < 10; i++{
          //statements  
        }

      在 Go 中也可使用类似 C 中 while 语句的写法,达到 while 语句的目的,此时控制语句中仅包含有控制条件判断语句。甚至 Go 可以完全省略 for 循环语句中的三个部分,此时为一个无限循环。

        i := 1
        for i < 100 {    // Go 中的 while 语句
            // statements  
        }
    
        for{          // Go 中的无限循环
            // statements  
        }

       

      条件语句

      使用 if 作为条件语句关键字,Go 中的 if 语句同样不需要使用 "()" 包围判断条件,但是需要使用 "{}" 来包围函数体。另外 Go 中的 if 语句支持在判断条件之前加入独立的初始化语句,该初始化部分在 if 判断执行之前执行,并仅在 if 语句内部可见(与 if 配对的 else 关键字对应的函数体中也可见)。

        i := 3
        if i < 10 {    // 判断语句
          // statements  
        }
    
        if i :=3; i < 10 {    // 条件语句前加入初始化语句
          // statements  
        } else {                // if 语句加入 else 时,else 关键字需与 "}" 同一行
          // statements  
        }
        

      switch

      Go 中的 switch 语句与 if 语句一样,可以在进行匹配的语句前插入一个初始化语句。与 C/C++ 所不同的是,Go 中只会执行匹配的 case 条件对应的语句,而不会执行后续相邻的 case 条件的语句(相当于每个 case 语句后默认存在 break )。

        switch i:=3; i {  // 可插入一个初始化语句
          case 1:
                //statements
          case 2:
                //statements
          default:
                //statements
        }

       同时 switch 语句的 case 条件并不需要是常量,甚至可以是函数。

         switch x{
          case 0:
          case f():  // x != 0 时,函数 f 会被调用...写法略浮夸  
        }

      switch 甚至可以忽略比较对象,实现类似 if-else 的逻辑。

        switch x:=3;{    // 初始化语句可省略
          case x < 5:
          case x < 10:
          default:  
        }

      

      复合类型

      struct 结构体

      struct 结构体为一个数据元素的集合,通过 type 关键字定义,通过 "." 来进行访问( 在 Go 中允许使用结构体变量或者变量的指针直接通过 "." 进行结构体元素访问)。

        type test struct{
          x int
          y int
        }

      对于定义的 struct 类型的变量,其结构体成员的初始值为对应类型的初始值,如 int 类型初始值为 0。用户也可以在定义时进行初始化。

        a := test{}        // 定义 struct 变量 a,其成员元素均为 0
        b := test{1, 2}    // 定义 struct 变量 b,其中 b.x = 1, b.y = 2
        c := test{ x:1}    // 定义 struct 变量 c,其中 c.x = 1, c.y = 0

      数组

      Go 中数组类型为 [n]T,其中 n 为数组中的元素个数,T 为数组元素的类型,n 为数组类型的一部分,数组的大小后续不能修改。

        var arr [3]int               // 3 个元素的整形数组
        arr2 := [3]int{ 0, 1, 2 }    // 另一种定义方式

      

      slice

      Go 中提供 slice 类型,用于访问数组中的元素。slice 类型为 []T,T 为其访问的元素的类型。slice 类型变量通过 arr[ low : high ] 的方式定义,其中 arr 为对应的数组,low 和 high 分别表示数组中索引,slice 类型可以访问数组中 [ low : high ) 范围的变量。当 low 被省略时,默认视为 0,high 被省略时,默认为数组长度。slice 类型可以看作对于数组中元素的引用,通过 slice 对元素的修改会对应修改数组中对应的元素。

        // 数组
        var arr [5]int = { 1, 2, 3, 4, 5 }
        //slice
        var a []int = arr[1:3]       // a[0]=2, a[1]=3 两个元素
        a[:]    
        a[0:5]                 // 均可索引整个数组
        
        b := []int{ 1, 2, 3 }        // 定义数组,并建立了对应的 slice b

      slice 类型变量包含有长度(length)和容量(capacity)两个信息,其中 length 表示 slice 类型可以访问的元素的个数,capacity 表示 slice 对应的数组从 slice 开始位置到数组结束位置的长度。可通过 len(a) 和 cap(a) 的方式查看 slice 的这两个属性。slice 未被初始化时,其默认值为 nil,length 与 capacity 属性均为 0,没有数组与之对应。

        a := []int{ 1, 2, 3, 4, 5, 6 }
        a[    : 0 ]        // len = 0, cap = 6
        a[    : 4 ]        // len = 4, cap = 6
        a[ 2 :    ]        // len = 2, cap = 4

       slice 变量还可以通过 Go 中内置的 make 函数进行创建,make 函数的使用形式为 make( T, args ) 。其中 T 为构建的类型,后接构建的参数。

        a := make( []int, 4 )       // 构建一个长度为 4 的数组的 slice,数组元素默认为 0
        b := make( []int, 3, 5 )    // 构建一个长度为 5 的数组的 slice,索引的slice 的 length 为 3

      slice 变量可以通过内置的 append 函数进行扩充。 append 函数签名为 func append( s []T, vs ... T ) []T,其中第一个参数为进行 append 操作的 slice 变量,后面为具体进行 append 的元素。当进行 append 操作的 slice 所对应的底层数组 capacity 足够时,append 操作对应会修改底层数组的值,若 capacity 不足时,append 操作会进行数组的重新分配,并返回新的 slice 结果。

       在 for 循环中,可以使用 range 关键字来简化对 slice 元素的遍历操作,每次循环过程中,range 会返回两个值,第一个为元素对应 slice 中的 index,第二个为 slice 在该 index 位置的值的拷贝。若不需要使用 range 返回的值的内容,可以使用 "_" 来忽略。同时,在 range 用法中,若只需要使用 slice 的索引,则可以省略第二个参数,直接使用 i := range a 即可。

        a := []int{ 1, 2, 3, 4, 5 }
        for index, _ := range a {
          // statements  
        }
    
        for i := range a {    // 若只是用索引,则可以直接省略第二个参数
            // statements
        }    

      更多关于 slice 介绍可以参考 Go Slices: usage and internals 。

      map

      Go 中提供 map 来建立 key 与 value 之间的关系。map 变量的默认值为 nil,无法进行任何操作。用户可以通过赋值或 make 函数获取可操作的 map。

        var m map[int]int           // m 为 nil,无法进行操作 
        m := map[int]int{}          // m 为空的 map,可以进行操作 
        m := make( map[int]int )
        m := make[int]int{ 1:2, 3:4 }  // m 为一个 int 到 int 的 map

      map 可支持的操作如下所示:

        a := map[int]int{}           // 获取一个空的 map 变量 a
        a[ 1 ] = 3                    // 添加/修改 key / value 关系
        b = a[ 1 ]                    // 返回 key 对应的 value 值,若对应的 key 不存在,直接返回对应类型的默认零值(注意不存在对应元素时不会自动创建,与 C++ map 不同)
        a[1] ++                       // 更新 key = 1 所对应的 value 值,若 key = 1 不存在,则会创建一个值为 0 的映射并继续操作 
        delete( a, 1 )                // 删除 map 中的 key
        value, ok := a[3]           // 测试 map 中是否含有对应的 key,若存在,则 ok 为 true,否则为 false,对应的 value 中包含有 key 对应的 value 或对应类型的初始零值
  • 相关阅读:
    《三极管应用分析精粹》终审完成,很快就要印刷了!
    关于SPAPI注册,SP-API注册,SPAPI申请,SP-API申请,开发人员资料注册,amazon亚马逊开发人员资料申请注册,amazon亚马逊销售合作伙伴 API申请注册,SP-API申请注册,amazon亚马逊Selling Partner API申请注册详细指导
    日照的那片海
    Cesium地下模式应用示例
    nginx-1.12.2解决跨域问题nginx.conf设置参考记录
    产品功能被像素级抄袭了。我们拿什么来保护原创的产品设计?
    网线的特征阻抗是多少?协议转换器上连接2m线,其非平衡阻抗是多少欧姆?
    ArrayList、LinkedList、HashSet、HashMap、Iterator
    java基础(枚举、包)
    微服务架构、ELK、ETL
  • 原文地址:https://www.cnblogs.com/yhjoker/p/15438187.html
Copyright © 2011-2022 走看看