Go 语言笔记
Table of Contents
1 Go 语言特点
- 命令式编程
- 静态类型
- 类似 C 语言的语法
- 编译成本地可执行的文件,没有运行虚拟机
- 不支持类, 使用结构体和方法编程
- 支持接口
- 没有 implementation inheritance, 可以使用 Type Embedding
- 函数是一等公民
- 函数可以返回多个值
- 可以使用闭包
- 支持指针, 但是没有指针运算
- 默认并发支持: Goroutines 和 Channels
2 基本语法
2.1 主函数
package main import "fmt" func main() { fmt.Println("Hello Go") }
2.2 声明
// 定义变量 var foo int // 定义,未初始化 var foo int = 42 // 定义并初始化 var foo, bar int = 42, 1302 // 定义多个参数,并初始化 var foo = 42 // 未给定类型,需要类型推导 foo := 42 // 只能在函数体中使用, 省略 var 关键字,不能提供类型 // 定义常量 const constant = "This is a constant" // iota 可以用于数字自增,起始值为 0 const ( _ = iota a b c = 1 << iota d ) mt.Println(a, b) // 1 2 (0 is skipped) mt.Println(c, d) // 8 16 (2^3, 2^4)
2.3 函数
// 定义函数 func functionName() {} // 参数类型在参数后 func functionName(param1 string, param2 int) {} // 同样类型的参数可以合并 func functionName(param1, param2 int) {} // 函数返回值 func functionName() int { return 42 } // 函数可以返回多个值 func returnMulti() (int, string) { return 42, "foobar" } var x, str = returnMulti() // 命名函数返回值 func returnMulti2() (n int, s string) { n = 42 s = "foobar" // n and s will be returned return } var x, str = returnMulti2()
2.4 闭包
func main() { // 定义函数 add := func(a, b int) int { return a + b } // 调用函数定义 fmt.Println(add(3, 4)) } // 闭包的情形 func scope() func() int{ outer_var := 2 foo := func() int { return outer_var} return foo } func another_scope() func() int{ // 编译错误,因为 outer_var 和 foo 未定义 outer_var = 444 return foo } // 使用闭包 func outer() (func() int, int) { outer_var := 2 inner := func() int { outer_var += 99 // 上一个作用域的 outer_var 变量值被改变 return outer_var } inner() return inner, outer_var // 返回 inner 函数和被修改的 outer_var 值, (改成了 101) }
2.5 变长参数列表
func main() { fmt.Println(adder(1, 2, 3)) // 6 fmt.Println(adder(9, 9)) // 18 nums := []int{10, 20, 30} fmt.Println(adder(nums...)) // 60 } func adder(args ...int) int { total := 0 // 变长列表 for _, v := range args { total += v } return total }
2.6 类型转换
var i int = 42 var f float64 = float64(i) var u uint = uint(f) // 等价语法 i := 42 f := float64(i) u := uint(f)
3 包
- 定义在每个源文件的头
- 可执行文件在 main 包中
- 规约: 包名是最后的文件夹
- Upper case 的标识会被导出,可以被其它包可见
- Lower case 的标识不会被导出,对其它包不可见
4 控制流
// if 语句 if x > 0 { } // 可以在 if 里面添加一个语句 if a := b + c; a < 42 { } // 循环语句, 循环只有 for, 没有 while, until for i := 1; i < 10; i++ { } // 实现类似 while 的结构 for ; i < 10; { } // 死循环写法, while(true) for { } // switch 语句 switch osType { case "darwin": fmt.Println("Mac OS") case "linux": fmt.Println("Linux") default: fmt.Println("Other") }
5 同构数据
5.1 数组
// 数组定义及操作,数组是定长的 var a [10]int a[3] = 42 i := a[3] // 定义并初始化数组 var a = [2]int{1, 2} a := [2]int{1, 2} a := [...]int{1, 2} // 编译器推断数组长度
5.2 分片
var a []int // 定义 slice, slice 和数组相似, 但是是变长的 var a = []int {1, 2, 3, 4} // 定义并初始化 a := []int{1, 2, 3, 4} // 定义并初始化 chars := []string{0:"a", 2:"c", 1: "b"} // ["a", "b", "c"] var b = a[lo:hi] // 取子分片,下标从 lo 到 hi-1 var b = a[1:4] // 取子分片,下标从 1 到 3 var b = a[:3] // missing low index implies 0 var b = a[3:] // missing high index implies len(a) a = append(a,17,3) // append items to slice a c := append(a,b...) // concatenate slices a and b // create a slice with make a = make([]byte, 5, 5) // first arg length, second capacity a = make([]byte, 5) // capacity is optional // create a slice from an array x := [3]string{"Лайка", "Белка", "Стрелка"} s := x[:] // a slice referencing the storage of x