Go的基础语法

不全,看文档的时候顺便写的笔记。

interface开始就没记了。后面go语言网络编程语法更是不知所云。

要不是项目有现成的代码抄我没准真的把文档看完。

感谢前人大爹了属于是。

Go

Go基础

变量定义

  • 完整声明

    • var variableName type
    • var vname1,vname2,vname3 type
    • var variableName type = value
    • var vname1,vname2,vname3 type = v1,v2,v3
  • 忽略类型

    • var vname1,vname2,vname3 = v1,v2,v3
  • 极简。只能用在函数内部

    • vname1,vname2,vname3 := v1,v2,v3
  • 声明了变量未使用会报错

变量类型

  • 支持复数。

    • complex128
    • complex64
    • 形式为RE+IMi
  • 支持Raw字符串,即字符串在代码中的形式就是打印的形式,没有字符转义,换行也会原样输出。形式是用``框起来

  • 错误类型。package的包里有一个errors。看那个包。

  • 数组

    • var arr [n]type
    • a := [n]type{….}
  • 切片slice

    • var fslice []type

    • slice := []byte {…..}

    • slice可以通过从已有数组里切割出来

      • slice := arr[2:5]
    • slice是引用类型。如果改变了slice里的值,那么引用的位置的值也会改变。

      • 就是说slice切了数组出来,改了slice,之前的数组里的元素也会变
    • slice的几个内置函数

      • len。获取slice的长度
      • cap。获取slice的最大容量
      • append。往slice里追加一个或者多个元素。然后返回一个类型一样的slice
        • 如果长度已经抵达了最大容量,append会申请新的内存-
    • Go的1.2版本后可以指定slice的容量。这样可以避免在切割后,访问到了不想令其访问的原数组部分。

      • slice := arr[2:4:7]
        • 其中7就是容量
  • map。字典类型。特点是不一定要用int类型来做key。可以是其他类型。也就是哈希表。

    • 格式为map[keyType]valueType
    • 删除map中的元素
      • delete(mapname,”vname”)
        • 删除名为vname的元素
  • make和new

    • 内建函数new本质上说跟其它语言中的同名函数功能一样:new(T)分配了零值填充的T类型的内存空间,并且返回其地址,即一个*T类型的值。用Go的术语说,它返回了一个指针,指向新分配的类型T的零值。有一点非常重要:
    • 内建函数make(T, args)new(T)有着不同的功能,make只能创建slicemapchannel,并且返回一个有初始值(非零)的T类型,而不是*T。本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个slice,是一个包含指向数据(内部array)的指针、长度和容量的三项描述符;在这些项目被初始化之前,slicenil。对于slicemapchannel来说,make初始化了内部的数据结构,填充适当的值。

流程和函数

流程语句

  • if不需要括号了

    1
    2
    3
    4
    5
    if x > 10 {
    fmt.Println("x is greater than 10")
    } else {
    fmt.Println("x is less than 10")
    }
    • 同时if可以在条件判断语句里声明一个变量。同时这个变量只在条件逻辑块内起作用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      // 计算获取值x,然后根据x返回的大小,判断是否大于10。
      if x := computedValue(); x > 10 {
      fmt.Println("x is greater than 10")
      } else {
      fmt.Println("x is less than 10")
      }

      //这个地方如果这样调用就编译出错了,因为x是条件里面的变量
      fmt.Println(x)
  • for也不需要括号了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package main
    import "fmt"

    func main(){
    sum := 0;
    for index:=0; index < 10 ; index++ {
    sum += index
    }
    fmt.Println("sum is equal to ", sum)
    }
    // 输出:sum is equal to 45
    • go里的循环可以省略到只剩条件语句。也就是直接变成了while

      1
      2
      3
      4
      sum := 1
      for sum < 1000 {
      sum += sum
      }
  • range函数

    • 针对于slice和map。用来读取slice和map的数据。

    • 返回值两个。元素的序号和元素的内容

      1
      2
      3
      4
      for k,v:=range map {
      fmt.Println("map's key:",k)
      fmt.Println("map's val:",v)
      }

      说实话我也不知道这个啥原理。很牛逼

      • 如果不需要序号元素的话可以省略

        1
        2
        3
        for _, v := range map{
        fmt.Println("map's val:", v)
        }
  • switch。

    • go的switch自带break。如果要强制往下执行就在每句句尾加一个fallthrough

函数

  • 可以返回多个返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package main
    import "fmt"

    //返回 A+B 和 A*B
    func SumAndProduct(A, B int) (int, int) {
    return A+B, A*B
    }

    func main() {
    x := 3
    y := 4

    xPLUSy, xTIMESy := SumAndProduct(x, y)

    fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
    fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
    }
  • defer语句

    Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。

    • 代码如下
1
2
3
4
5
6
7
8
9
10
11
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
  • 如果有很多调用defer,那么defer是采用后进先出模式,所以如下代码会输出4 3 2 1 0
1
2
3
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
  • 可以用ype来定义函数的类型