安装 Golang 在 http:///dl/ 可以下载到 Golang。安装文档:http:///doc/install。 Hello Go 我们先创建一个文件 hello.go: 复制代码 代码如下: package main import 'fmt' func main() { fmt.Printf('hello Golang\n'); } 执行此程序: 复制代码 代码如下: go run hello.go 包 Golang 程序由包(packages)组成,程序从 main 包开始运行: 复制代码 代码如下: package main 此语句表示此文件属于 main 包(多个源文件可以属于同一个包)。import 语句后接上包所在的路径(被叫做包路径或导入路径),一个目录中放置一个包,通常的做法是,目录名和包名相同: 复制代码 代码如下: import ( 'fmt' 'math/rand' ) 这里的 “fmt” 和 “math/rand” 为包路径(导入路径)。上面的 import 语句也可以这样写: 复制代码 代码如下: import 'fmt' import 'math/rand' 我们导入了包之后,就可以通过 “包名.name” 来引用导出的 name 了,例如: 复制代码 代码如下: import 'fmt' // fmt 包导出了 Printf fmt.Printf('hello Golang\n'); 在 Golang 中,一个名字如果首字母大写则表示此名字被导出。 函数 复制代码 代码如下: package main import 'fmt' func add(x int, y int) int { return x + y } func main() { fmt.Println(add(42, 13)) } 需要注意的就是,变量名在类型之前,这和很多语言都不一样。另外 x int, y int 也可以写为 x, y int: 复制代码 代码如下: func add(x, y int) int { return x + y } 函数可以返回多个值: 复制代码 代码如下: package main import 'fmt' func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap('hello', 'world') fmt.Println(a, b) } 返回值可以被指定变量名,并且像变量一样使用: 复制代码 代码如下: package main import 'fmt' func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return } func main() { fmt.Println(split(17)) } 可以看到 split 函数直接使用 return 语句而不用带参数。 变量 变量的声明使用 var 语句: 复制代码 代码如下: var i int var c, python, java bool 变量在声明时可以进行初始化: 复制代码 代码如下: var x, y int = 1, 2 var i, j = true, 'hello' 我们看到,初始化时可以指定也可以不指定变量类型。 复制代码 代码如下: package main func main() { var x, y int = 1, 2 i, j := true, 'hello' } := 操作符左边为变量,右边为值。 数据类型 基本数据类型: 1.bool 类型转换使用表达式 T(v),含义为将 v 转换为类型 T: 复制代码 代码如下: var i int = 42 var f float64 = float64(i) i := 42 f := float64(i) 类型转换总需要显式的进行。 使用 const 来声明常量: 复制代码 代码如下: const Pi = 3.14 const ( Big = 1 <> Small = Big >> 99 ) 控制语句 for 语句 Golang 使用(且只使用)for 来进行循环(没有 while 语句): 复制代码 代码如下: package main func main() { sum := 0 for i := 0; i < 10;="" i++=""> sum += i } // 这种写法等价于 C/C++ 等语言中的 while 语句 for sum < 1000=""> sum += sum } } 区别于 C/C++ 等语言,使用 for 语句时不需要 () 并且 {} 是必须的(后面谈到的 if、switch 在此语法处理上也是一样的)。如果需要无限循环,那么使用: 复制代码 代码如下: for { } if 语句 if 语句可以在执行条件判断前带一个语句(这常被叫做 if 带上一个短语句),此语句中变量的生命周期在 if 语句结束后结束。例如: 复制代码 代码如下: package main import ( 'fmt' 'math/rand' ) func main() { if n := rand.Intn(6); n <= 2="">=> fmt.Println('[0, 2]', n) } else { fmt.Println('[3, 5]', n) } // 这里开始无法使用变量 n } switch 复制代码 代码如下: package main import ( 'fmt' 'runtime' ) func main() { fmt.Print('Go runs on ') // switch 类似 if 可以带上一个短语句 switch os := runtime.GOOS; os { case 'darwin': fmt.Println('OS X.') case 'linux': fmt.Println('Linux.') default: // freebsd, openbsd, // plan9, windows... fmt.Printf('%s.', os) } } 不像 C/C++ 等语言,Golang 中无需使用 break 语句来跳出 switch。另外,switch 可以没有条件: 复制代码 代码如下: package main import ( 'fmt' 'time' ) func main() { t := time.Now() switch { case t.Hour() <> fmt.Println('Good morning!') case t.Hour() <> fmt.Println('Good afternoon.') default: fmt.Println('Good evening.') } } defer 一个 defer 语句能够将一个函数调用加入一个列表中(这个函数调用被叫做 deferred 函数调用),在当前函数调用结束时调用列表中的函数。范例: 复制代码 代码如下: func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } defer src.Close() dst, err := os.Create(dstName) if err != nil { return } defer dst.Close() return io.Copy(dst, src) } deferred 函数调用按先进后出的顺序执行: 复制代码 代码如下: package main import 'fmt' func main() { for i := 0; i < 5;="" i++=""> // 输出 43210 defer fmt.Print(i) } } 结构(structs) 结构是一个域的集合: 复制代码 代码如下: package main import 'fmt' type Vertex struct { X int Y int } func main() { v := Vertex{1, 2} v.X = 4 fmt.Println(v) } Golang 中是存在指针的,但是指针不支持算术运算: 复制代码 代码如下: p := Vertex{1, 2} // {1, 2} 为 struct literal q := &p // q 类型为 *Vertex q.X = 2 // 直接访问域 X 就像上面看到的,struct 的 literal 由 {} 包裹,在 struct literal 中我们可以使用 Name: 这样的语法来为特定域设置值: 复制代码 代码如下: type Vertex struct { X, Y int } r := Vertex{X: 3} // 这时候 Y 为 0 new 函数 我们可以通过表达式 new(T) 分配一个被初始化为 0 且类型为 T 的值,并且返回指向此值的指针,用法如下: 复制代码 代码如下: var p *T = new(T) p := new(T) 更详尽的例子: 复制代码 代码如下: package main import 'fmt' type Vertex struct { X, Y int } func main() { v := new(Vertex) fmt.Println(v) v.X, v.Y = 11, 9 fmt.Println(v) } 数组和 slice [n]T 在 Golang 中是一个类型(就像 *T 一样),表示一个长度为 n 的数组其元素类型为 T。范例: 复制代码 代码如下: package main import 'fmt' func main() { var a [2]string a[0] = 'Hello' a[1] = 'World' fmt.Println(a[0], a[1]) fmt.Println(a) } 注意,数组长度无法被改变。 slice 是一个数据结构,其指向一个数组某个连续的部分。slice 用起来很像数组。[]T 为 slice 类型,其中元素类型为 T: 复制代码 代码如下: package main import 'fmt' func main() { // 构建一个 slice p := []int{2, 3, 5, 7, 11, 13} fmt.Println('p ==', p) for i := 0; i < len(p);="" i++=""> fmt.Printf('p[%d] == %d\n', i, p[i]) } } 表达式 s[lo:hi] 用于创建一个 slice,新创建的 slice 的元素为 s 中 [lo, hi) 位置的元素。 创建 slice 使用 make 函数(而不是用 new 函数,因为需要设置额外的参数来控制 slice 的创建): 复制代码 代码如下: // len(a) 为 5 a := make([]int, 5) 这里 make 函数会创建一个数组(其元素初始化为 0)并返回一个 slice 指向此数组。make 可以带第三个参数,用于指定容量: 复制代码 代码如下: // len(b) 为 0 // cap(b) 为 5 b := make([]int, 0, 5) b = b[:cap(b)] // len(b)=5, cap(b)=5 b = b[1:] // len(b)=4, cap(b)=4 一个没有值的 slice 是 nil,长度和容量都为 0。 复制代码 代码如下: package main import 'fmt' func main() { var z []int fmt.Println(z, len(z), cap(z)) if z == nil { fmt.Println('nil!') } } range range 被用在 for 中来迭代一个 slice 或者一个 map: 复制代码 代码如下: package main import 'fmt' var s = []int{1, 2, 3} func main() { for i, v := range s { fmt.Println(i, v) } // 只需要值,使用 _ 忽略索引 for _, v := range s { fmt.Println(v) } // 只需要索引 for i := range s { fmt.Println(i) } } map map 用于映射 key 到 value(值)。map 可以通过 make 来创建(而非 new): 复制代码 代码如下: package main import 'fmt' type Vertex struct { Lat, Long float64 } var m map[string]Vertex func main() { m = make(map[string]Vertex) m['Bell Labs'] = Vertex{ 40.68433, -74.39967, } fmt.Println(m['Bell Labs']) } map iteral 很像 struct literal: 复制代码 代码如下: var m = map[string]Vertex{ // 这里 Vertex 可以省略不写 'Bell Labs': Vertex{ 40.68433, -74.39967, }, 'Google': Vertex{ 37.42202, -122.08408, }, } 使用 [] 来访问 map 中的值,使用 delete 来删除 map 中的值: 复制代码 代码如下: m[key] = elem elem = m[key] delete(m, key) 如果需要检查 map 中某 key 是否存在使用: 复制代码 代码如下: elem, ok = m[key] elem 表示 key 的值(key 不存在时,elem 为 0),ok 表示 key 是否存在。 闭包 Golang 中函数也是一个值(就像 int 值一样),且函数可以是一个闭包。闭包是一个引用了外部变量的函数。看一个例子: 复制代码 代码如下: package main import 'fmt' func adder() func(int) int { sum := 0 // 返回一个闭包,此闭包引用了外部变量 sum return func(x int) int { sum += x return sum } } func main() { a := adder() fmt.Println(a(9527)) }
|
|