Go学习笔记01-变量|类型|常量|函数|包|if-else语句|循环|switch语句

变量

  • 声明单个变量,e.g. var age int,变量未被赋值,Go会自动将其初始化为该变量类型的零值。
  • 声明变量并初始化:e.g. var age int = 29
  • Go能够根据初始值自动判断变量的类型:e.g. var age = 29
  • 声明多个变量:e.g. var width, height intvar width, height int = 100, 50
  • 在一个语句中声明不同类型的变量:
  package main
  
  import "fmt"
  
  func main() {
      var (
          name   = "staught"
          age    = 29
          height int
      )
      // Output: My name: staught, age: 29, height: 0
      fmt.Printf("My name: %s, age: %d, height: %d\n", name, age, height)
  }
  • 简短声明:e.g. name, age := "staught", 29,需要注意:
    • 简短声明要求:=操作符左边的所有变量都有初始值;
    • 简短声明要求:=操作符左边至少有一个变量是尚未声明的。

类型

  • Go支持的基本类型
    • bool
    • int8, int16, int32, int64, int
    • uint8, uint16, uint32, uint64, uint
    • float32, float64
    • complex64, complex128
    • byte
    • rune
    • string
  • int根据不同的底层平台,表示32或64位整型。除非对整型的大小有特定的需求,否则我们通常应该使用int表示整型。
  • uint根据不同的底层平台,表示32或64位无符号整型。
  • float64是浮点数的默认类型,比如a := 5.67,那么a的类型默认是float64。
  • byte是uint8的别名。
  • rune是int32的别名。
  • 在Golang中,字符串是字节的集合。
  • Go有着非常严格的强类型特征,它没有自动类型提升或类型转换。把v转换为T类型的语法是:T(v)

常量

  • Go语言的字面常量更接近我们自然语言中的常量概念,它是无类型的。只要这个常量在相应类型的值域范围内,就可以作为该类型的常量,比如常量-12,它可以赋值给int, uint, int32, int64, float32, float64, complex64, complex128等类型的变量。
  • 只需记住:常量可以赋值给“合适的”类型,而不需要类型转换,举个例子:
  // 以下代码,f1的赋值正常,但f2的编译不通过
  const a = 0
  var b = 0 // int 
  
  var f1 float64 = a 
  var f2 float64 = b // cannot use b (type int) as type float64 in assignment
  
  fmt.Println(f1, f2)

函数

  • 函数声明通用语法如下:
  func functionname(parametername type) returntype {
      // 函数体
  }
  • 函数的声明中如果有连续若干个参数,它们的类型一致,那么可以只在最后一个参数后添加该类型,例如:func calc(price int, num int)可以简写为func calc(price, num int)
  • Go语言支持一个函数可以有多个返回值,如果一个函数有多个返回值,那么在声明中这些返回值必须用()括起来,例如:func rect(length, width float64) (float64, float64)
  • Go语言支持命名返回值,一旦命令了返回值,可以认为这些值在函数的开始就被声明为变量并初始化为相应类型的零值了(返回值命名不是强制的,但是它们可以使得代码更加健壮和清晰),可以在函数体内当局部变量来使用,例如:
  func rect(length, width float64) (area, perimeter float64) {
      area = length * width
      perimater = (length+width)*2
      return // 不需要明确指定返回值,默认会返回area和perimeter的值
  }
  • _在Go语言中被用作空白符,可以用来表示任何类型的任何值。它是用来跳过不需要的计算结果的,例如函数func rect(length, width float64) (area, perimeter float64),假设我们只需要计算面积,而不关心周长,那么只需通过空白符将周长的返回值丢弃即可:area, _ := rect(10.8, 5.6)

  • package packagename这行代码指定了某一源文件属于一个包,它应该放在每一个源文件的第一行。
  • 属于某一个包的源文件都应该放置于一个单独命名的文件夹里,按照Go的惯例,应该用包名命名该文件夹。
  • 导入自定义包的语法:import path,必须指定自定义包相对于工作区src文件夹的相对路径。
  • 在Go中,任何以大写字母开头的变量或者函数都是被导出的名字,其它包只能访问被导出的函数和变量。
  • 所有包都可以包含一个init函数,init函数不应该有任何返回值类型和参数,在我们的代码中也不能显示地调用它。init函数形式如下:
  func init() {
      // init函数可用于执行初始化任务,也可用于在开始执行之前验证程序的正确性
  }
  • 包的初始化顺序:
    • 首先初始化包级别的变量;
    • 紧接着调用init函数,包可以用多个init函数(在一个文件或分布于多个文件中),它们按照编译器解析它们的顺序进行调用。
  • 如果一个包导入了另一个包,会先初始化被导入的包。
  • 尽管一个包可能会被导入多次,但是它只会被初始化一次。
  • 导入了包,却不在代码中使用它,这在Go中是非法的。有时候我们导入一个包,只是为了确保它进行了初始化,而无需使用包中的任何函数或变量。这种情况可以使用空白标识符,如下所示:
  import (
      _ "geometry/rectangle"
  )

if-else语句

  • if语句的语法如下所示,在Go语言里的{}是必要的,即使在{}之间只有一条语句:
  if condition {
      // do something
  }
  • if语句还有可选的else ifelse部分:
  if condition {
  } else if condition {
  } else {
  }
  • if还有另外一种形式,它包含一个statement可选语句部分,该组件在条件判断之前运行,它的语法是:
  if statement; condition {
  }
  • else语句应该在if语句的大括号}之后的同一行中,否则编译不会通过。

循环

  • for是Go语言唯一的循环语句。
  • for循环语法如下所示,第一部分为初始化表达式或赋值语句,第二个为循环条件判定表达式,第三个为循环变量修正表达式,在Go中这三个组成部分都是可选的。
  for initialisation; condition; post {
  }
  • for循环的三个组成部分都去掉就成了无限循环:
  for {
  }
  • for循环中可以声明和操作多个变量,举个例子:
  package main

  import "fmt"

  func main() {
      for i, j := 10, 1; i <= 19 && j <= 10; i, j = i+1, j+1 {
          fmt.Printf("%d * %d = %d\n", i, j, i*j)
      }
  }
  // Output:
  // 10 * 1 = 10
  // 11 * 2 = 22
  // 12 * 3 = 36
  // 13 * 4 = 52
  // 14 * 5 = 70
  // 15 * 6 = 90
  // 16 * 7 = 112
  // 17 * 8 = 136
  // 18 * 9 = 162
  // 19 * 10 = 190

switch语句

  • switch是一个条件语句,用于将表达式的值与可能匹配的选项列表进行比较,并根据匹配情况执行相应的代码块,在选项列表中,case不允许出现重复项。它是替代多个if else子句的常用方式。
  • default不一定只能出现在switch语句的最后,但我们一般把它放到最后,这样更符合逻辑。
  • 在表达式求值之前,switch可以选择先执行一个语句,举个例子:
  switch num := 1*3; num {
  case 1:
      //
  case 2:
      //
  case 3:
      // will be executed
  default:
      //
  }
  • 通过用逗号分隔,可以在一个case中包含多个表达式:
  package main

  import "fmt"

  func main() {
      letter := "i"
      switch letter {
      case "a", "e", "i", "o", "u":
          fmt.Println("vowel") // will be executed
      default:
          fmt.Println("not a vowel")
      }
  }
  • 在switch语句中,表达式是可选的,可以被省略。如果省略表达式,则表示这个switch语句等同于switch true,并且每个case表达式都被认定为有效,相应的代码块也会被执行。举个例子,如下代码,switch中缺少表达式,因此默认它为true,true值会和每一个case的求值结果进行匹配,所以程序将执行case num >= 51 && num <= 100:下的代码块。这种类型的switch语句可以替代多个if else子句。
  num := 75
  switch {
  case num >= 0 && num <= 50:
      //
  case num >= 51 && num <= 100:
      // will be executed
  case num >= 101:
      //
  }
  • 在Go中,每执行完一个case后,会从switch语句中跳出来,不再做后续case的判断和执行。使用fallthrough语句可以在已经执行完成的case之后,把控制权转移到下一个case的执行代码中(也就是不做case中的匹配直接执行)。还有,fallthrough语句应该是case子句的最后一个语句,如果出现在中间编译器会报错。

reference:

https://studygolang.com/articles/11756
https://studygolang.com/articles/11869
https://studygolang.com/articles/11872
https://studygolang.com/articles/11892
https://studygolang.com/articles/11893
https://studygolang.com/articles/11902
https://studygolang.com/articles/11924
https://studygolang.com/articles/11957