夜雪天狼
学习笔记
技术博文
转载备份
心灵鸡汤
目录
go语言基础
发布者:caijw
阅读量:62585
发布时间:2018-09-30 09:00:00
# 变量 -vertical- ## 变量定义的两个步骤: 1. 定义变量:分配内存空间 2. 初始化变量:为变量进行赋值 Comment: 注意:变量初始化前,必须进行定义 -vertical- ## 定义变量 ```go var 变量名字[,变量名2...] [变量类型]//定义一个变量,可以指定变量类型 变量名字 = 变量值 //为变量赋值,赋值前必须定义变量 /* 定义变量并赋值 如果指定了类型,那么变量值的类型要与指定类型一致,否则会报错 如果没有指定类型,则以变量值类型为准 */ var 变量名字[,变量名2...] [变量类型] = 变量值[,变量值2...] /* 语法糖:将变量定义和赋值整合在一起,注意,此时不能指定变量类型 且只能用于定义局部变量(后面会解释局部变量) 以下语句等价于:var 变量名字[,变量名2...] = 变量值[,变量值2...]*/ 变量名[,变量名2...] := 变量值[,变量值2...] /* _(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃 在这个例子中,我们将值35赋予b,并同时丢弃34 */ _, b := 34, 35 ``` Comment: 不能对已经定义的变量使用:=操作 -vertical- ## 变量基本类型 1. bool 2. string 3. int8 int16 int32(rune) int64(int) 4. uint8(byte) uint16 uint32 uint64(uint) 5. float32 float64 -vertical- ## 变量的命名与作用域 变量的命名规则遵循骆驼命名法,即首个单词小写,每个新单词的首字母大写,例如:numShips 和 startDate 但如果你的全局变量希望能够被外部包所使用,则需要将首个单词的首字母也大写 一个变量(常量、类型或函数)在程序中都有一定的作用范围,称之为作用域。如果一个变量在函数体外声明,则被认为是全局变量,可以在整个包甚至外部包(被导出后)使用,不管你声明在哪个源文件里或在哪个源文件里调用该变量 在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量 在后面会介绍到的流程控制(如if 和 for )中,声明的变量的作用域只在相应的代码块内。一般情况下,局部变量的作用域可以通过代码块(用大括号括起来的部分)判断 尽管变量的标识符必须是唯一的,但你可以在某个代码块的内层代码块中使用相同名称的变量,则此时外部的同名变量将会暂时隐藏(结束内部代码块的执行后隐藏的外部同名变量又会出现,而内部同名变量则被释放),你任何的操作都只会影响内部代码块的局部变量 -vertical- # 可见性规则与导出 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像PHP中的 public) 标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像php中的 private ) Comment: 准确的说是像java中的default而不是private -separator- # 流程判断 1. if else 2. switch 3. goto 4. for循环 -vertical- ## if else ```go if x > 10 { fmt.Println("x is greater than 10") } else { fmt.Println("x is less than 10") } //和其他语言不同之处 赋值和判断在一个语句块内 if x := computedValue(); x > 10 { fmt.Println("x is greater than 10") } else { fmt.Println("x is less than 10") } ``` -vertical- ## switch ```go /* 和php的switch基本一致,不同点如下 无需手动写break,每个case结束后自动退出switch 可以使用fallthrough强制执行后面的case代码 */ integer := 6 switch integer { case 5: fmt.Println("The integer was <= 5") fallthrough case 6: fmt.Println("The integer was <= 6") fallthrough case 7: fmt.Println("The integer was <= 7") fallthrough default: fmt.Println("default case") } ``` -vertical- ## goto ```go //Go有goto语句——请明智地使用它。用goto跳转到必须在当前函数内定义的标签。 func myFunc() { i := 0 Here: //这行的第一个词,以冒号结束作为标签 println(i) i++ goto Here //跳转到Here去 } ``` -vertical- ## for循环 ```go //for循环数组和php差不多 sum := 0; for index:=0; index < 10 ; index++ { sum += index } fmt.Println("sum is equal to ", sum) //循环map如下,相当于foreach for k,v:=range map { fmt.Println("map's key:",k) fmt.Println("map's val:",v) } //由于Go支持多值返回, 而对于声明而未被调用的变量, 编译器会报错, //在这种情况下, 可以使用_来丢弃不需要的返回值 例如 for _, v := range map{ fmt.Println("map's val:", v) } //break和continue 与 php基本一致 ``` -separator- # 函数 -vertical- ## 多返回值处理 ```go //接收函数多返回值,为xPLUSy, xTIMESy := SumAndProduct(x, y) //或 _, xTIMESy := SumAndProduct(x, y) 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) } ``` -vertical- ## 引用传递 ```go /* 和php的不同之处 func add1(a *int) int 用* 表示引用传递 调用之处 x1 := add1(&x) 和php基本一致 */ func add1(a *int) int { // 请注意, *a = *a+1 // 修改了a的值 return *a // 返回新值 } func main() { x := 3 fmt.Println("x = ", x) // 应该输出 "x = 3" x1 := add1(&x) // 调用 add1(&x) 传x的地址 fmt.Println("x+1 = ", x1) // 应该输出 "x+1 = 4" fmt.Println("x = ", x) // 应该输出 "x = 4" } ``` -vertical- ## 不定参数 ```go //在函数体中,变量arg是一个int的slice func myfunc(arg ...int) {} for _, n := range arg { fmt.Printf("And the number is: %d\n", n) } ``` -separator- # defer Defer 用来保证一个函数调用会在程序执行的最后被调用。通常用于资源清理工作 -vertical- ## 代码演示 ```go // 假设我们想创建一个文件,然后写入数据,最后关闭文件 func main() { // 在使用createFile得到一个文件对象之后,我们使用defer // 来调用关闭文件的方法closeFile,这个方法将在main函数 // 最后被执行,也就是writeFile完成之后 f := createFile("/tmp/defer.txt") defer closeFile(f) writeFile(f) } func createFile(p string) *os.File { fmt.Println("creating") //省略实现 } func writeFile(f *os.File) { fmt.Println("writing") } func closeFile(f *os.File) { fmt.Println("closing") f.Close() } ``` -vertical- ## defer采用先进后出模式 ```go //如下代码会输出4 3 2 1 0 for i := 0; i < 5; i++ { defer fmt.Printf("%d ", i) } ``` -separator-