UP | HOME

Go 语言笔记

Table of Contents

1 Go 语言特点

  1. 命令式编程
  2. 静态类型
  3. 类似 C 语言的语法
  4. 编译成本地可执行的文件,没有运行虚拟机
  5. 不支持类, 使用结构体和方法编程
  6. 支持接口
  7. 没有 implementation inheritance, 可以使用 Type Embedding
  8. 函数是一等公民
  9. 函数可以返回多个值
  10. 可以使用闭包
  11. 支持指针, 但是没有指针运算
  12. 默认并发支持: 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

  1. 定义在每个源文件的头
  2. 可执行文件在 main 包中
  3. 规约: 包名是最后的文件夹
  4. Upper case 的标识会被导出,可以被其它包可见
  5. 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

5.3 范围

6 结构体

7 参考连接

Last Updated 2021-09-21 Tue 11:22. Created by Jinghui Hu at 2021-08-11 Wed 11:41.