1. Go语言组成

    • 包声明
    • 引入包
    • 函数
    • 变量(当标识符(包括变量,常量类型,函数名结构字段等等)以一个大写字母开头时,可以被外部调用,称为导出)
    • 语句&表达式
    • 注释
  2. 在Go程序中,一个语句以一行分隔,而C语言家族使用分号;隔开.

  3. 标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

  4. go代码中会使用的25个关键字或保留字:

    break default func interface select case defer
    go map struct chan else goto package
    switch const fallthrough if range type continue
    for import return var
  5. Go语言的36个预定义标识符:

    append bool byte cap close complex complex64 complex128 uint16
    copy false float32 float64 imag int int8 int16 uint32
    int32 int64 iota len make new nil panic uint64
    print println real recover string true uint uint8 uintptr
  6. go语言的字符串是由单个字节连接起来的.go语言使用的是UTF-8编码的Unicode文本

  7. 可以省略var定义关键字,而是使用类似c:=123形式,注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。

  8. 如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误,如下:

    1
    2
    3
    4
    
    func main() {
    var a string = "abc"
    fmt.Println("hello, world")
    } # a declared and not used
    

    ``

  9. 如果你想要交换两个变量的值,则可以简单地使用 a, b = b, a。

  10. 空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。 _ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

  11. 并行赋值也被用于当一个函数返回多个返回值时,比如这里的 val 和错误 err 是通过调用 Func1 函数同时得到:val, err = Func1(var1)

  12. Go语言常量数据类型只可以是布尔型、数字型和字符串型。

  13. iota,特殊变量,可以被修改器修改。在每一个const关键字出现时,被置为0,然后再下一个const出现前,每一次iota,其所代表的数字会自动加1.iota可以用于迭代器

  14. Go语言运算符:

    • 算术运算符:+,-,*,/,%,++,–
    • 关系运算符:==,!=,>,<,>=,<=
    • 逻辑运算符:&&,||,!
    • 位运算符:&,|,^,«,»
    • 赋值运算符:=,+=,-=,*=,/=,%=,«=,»=,&=,^=,|=
    • 其他运算符: &(返回变量存储地址),*(指针变量)
  15. 位运算符详细说明:(A=0011 1100;B=0000 1101)

    运算符 描述 实例
    & 按位与运算符”&“是双目运算符。 其功能是参与运算的两数各对应的二进位相与。 (A & B) 结果为 12, 二进制为 0000 1100
    \ 按位或运算符”\
    ^ 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (A ^ B) 结果为 49, 二进制为 0011 0001
    « 左移运算符"«"是双目运算符。左移n位就是乘以2的n次方。 其功能把"«"左边的运算数的各二进位全部左移若干位,由"«"右边的数指定移动的位数,高位丢弃,低位补0。 A « 2 结果为 240 ,二进制为 1111 0000
    >> 右移运算符"»"是双目运算符。右移n位就是除以2的n次方。 其功能是把"»"左边的运算数的各二进位全部右移若干位,“»"右边的数指定移动的位数。 A » 2 结果为 15 ,二进制为 0000 1111
  16. 运算符优先级:

    优先级 运算符
    7 ^ !
    6 * / % « » & &^
    5 + - \
    4 == != < <= >= >
    3 <-
    2 &&
    1 \
  17. select语句:每个case都必须是一个通信;所有channel表达式都会被求值;所有被发送的表达式都会被求值;如果任意某个通信可以进行,它就执行;其他被忽略。如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。 否则: 14. 如果有default子句,则执行该语句。 15. 如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。

  18. Go 语言的 goto 语句可以无条件地转移到过程中指定的行。goto语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能,但是,在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。

  19. 引用传递,例子:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    package main
    	
    import "fmt"
    	
    func main() {
       /* 定义局部变量 */
       var a int = 100
       var b int= 200
    	
       fmt.Printf("交换前,a 的值 : %d\n", a )
       fmt.Printf("交换前,b 的值 : %d\n", b )
    	
       /* 调用 swap() 函数
       * &a 指向 a 指针,a 变量的地址
       * &b 指向 b 指针,b 变量的地址
       */
       swap(&a, &b)
    	
       fmt.Printf("交换后,a 的值 : %d\n", a )
       fmt.Printf("交换后,b 的值 : %d\n", b )
    }
    	
    func swap(x *int, y *int) {
       var temp int
       temp = *x    /* 保存 x 地址上的值 */
       *x = *y      /* 将 y 值赋给 x */
       *y = temp    /* 将 temp 值赋给 y */
    }
    
  20. 函数做为值

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    	
    package main
    	
    import (
        "fmt"
        "math"
    )
    	
    func main() {
        getSquareRoot := func(x float64) float64 {
            return math.Sqrt(x)
        }
        fmt.Println(getSquareRoot(9))
    	
    }
    
  21. 闭包操作(Go 语言支持匿名函数,可作为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。):

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    package main
    import (
        "fmt"
    )
    func getSequence() func() int {
        i := 0
        return func() int {
            i++
            return i
        }
    }
    func main()  {
        nextNumber := getSequence()
        fmt.Println(nextNumber())
        fmt.Println(nextNumber())
        fmt.Println(nextNumber())
        nextNumber1 := getSequence()
        fmt.Println(nextNumber1())
        fmt.Println(nextNumber1())
    }
    
  22. Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:

    1
    2
    3
    
    func (variable_name variable_data_type) function_name() [return_type]{
       /* 函数体*/
    }
    

    example:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // method_statement.go
    	
    package main
    	
    import (
        "fmt"
    )
    	
    type Circle struct {
        radius float64
    }
    	
    func main() {
        var c1 Circle
        c1.radius = 10.00
        fmt.Println("Area of Circle(c1) = ", c1.getArea())
    }
    	
    func (c Circle) getArea() float64 {
        return 3.14 * c.radius * c.radius
    }
    //result:Area of Circle(c1) =  314
    
  23. Go 语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    // local_global_var.go
    	
    package main
    	
    import (
        "fmt"
    )
    	
    var b string = "Golang"
    	
    func main() {
        var a string = "lryong"
        var b string = "future" //函数内的局部变量会被优先考虑
        fmt.Printf("a is %s,b is %s\n", a, b)
    }
    
  24. 数组初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

  25. 多维数组:var threedim [5][10][4]int

  26. Go空指针:当一个指针被定义后没有分配到任何变量时,它的值为 nil。nil 指针也称为空指针。nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。一个指针变量通常缩写为 ptr。

    • example:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    // nil_pointer.go
    package main
    	
    import (
        "fmt"
    )
    	
    func main() {
        var ptr *int
        /*空指针判断*/
        if ptr == nil { //ptr空指针
            fmt.Println("Has not assigned pointer")
        } else {
            fmt.Println("Has assigned pointer")
        }
        fmt.Printf("ptr's value is %d\n", ptr) //空指针
    }
    
  27. 指针数组:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    // pointer_array.go
    package main
    	
    import (
        "fmt"
    )
    	
    const MAX int = 3
    	
    func main() {
        var a = [3]int{10, 100, 1000}
        var ptr [MAX]*int
        for i := 0; i < MAX; i++ {
            ptr[i] = &a[i] //整数地址赋值给指针数组
        }
    	
        for i := 0; i < MAX; i++ {
            fmt.Printf("a[%d] = %d\n", i, *ptr[i])
        }
    	
    }
    
  28. 指向指针的指针:var ptr **int

    • example:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
      // pointer_to_pointer.go
      package main
            
      import (
          "fmt"
      )
            
      func main() {
          var a int
          var ptr *int
          var pptr **int
      
          a = 555
          ptr = &a
          pptr = &ptr
            
          fmt.Printf("变量a = %d\n", a)
          fmt.Printf("指针变量*ptr = %d\n", *ptr)
          fmt.Printf("指针变量**ptr = %d\n", **pptr)
      }
      
  29. Go语言指针作为函数参数,Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。