小技巧

  1. 修改了vscode的tasks.json文件的配置,控制台执行 command + shift + B 可以代替执行go run file.go,多个文件的时候更实用

语言结构

1
2
3
4
5
6
7
8
9
// hello.go
package main // 非注释的第一行,指定包名

import "fmt" // fmt 包实现了格式化 IO(输入/输出)的函数

func main() { // 程序开始执行的函数
fmt.Println("hello go") // 相当于fmt.Print("hello, go\n")
}
// 执行 go run hello.go

  1. 不能使用单引号
  2. package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包
  3. main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)
  4. 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,可以被外部包的代码所使用;以小写字母开头,是在包的内部可见可用
  5. “{”不能放在单独的一行

基础语法

  1. 一行代表一个语句结束,不需要分号;一行写多个语句时,用分号区分

数据类型
数据类型的出现是为了把数据分成所需内存大小不同的数据,充分利用内存

  1. 布尔型: true false
  2. 数字类型: 整型 int(uint8、uint16、uint32、uint64、 int8、 int16、 int32、 int64),浮点型 float32(IEEE-754 32位浮点型数)、float64(IEEE-754 64位浮点型数)、complex64(32 位实数和虚数)、 complex128(64 位实数和虚数)和其他 byte(类似 uint8)、rune(类似 int32)、uint(32 或 64 位)、int(与 uint 一样大小)、 uintptr(无符号整型,用于存放一个指针)
  3. 字符串类型
  4. 派生类型:指针(Pointer)、数组、结构化(struct)、Channel 类型、函数类型、切片类型、接口类型(interface)、Map类型

Go语言变量

1
var b, c int = 1, 2

  1. 第一种,指定变量类型:类型写在最后,未指定初始值时,初始值:数值类型为0、布尔类型为false、字符串为””、以下几种为nil:

    1
    2
    3
    4
    5
    6
    var a *int
    var a []int
    var a map[string] int
    var a chan int
    var a func(string) int
    var a error // error 是接口
  2. 第二种,根据值自行判定变量类型

  3. 第三种,省略 var(初始化声明,是使用变量的首选形式,但只能被用在函数体内), 注意 := 左侧如果没有声明新的变量,就产生编译错误

    1
    2
    3
    var intVal int 
    intVal :=1 // 重复声明intVal,会产生编译错误
    intVal,intVal1 := 1,2 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
  4. 多变量声明

    1
    2
    3
    4
    5
    // 声明全局变量
    var (
    vname1 v_type1
    vname2 v_type2
    )
  5. 值类型和引用类型:值类型存储在栈中,可以通过&i 来获取变量 i 的内存地址,内存地址会根据机器的不同而有所不同

  6. 如果声明了一个局部变量却没有在相同的代码块中使用它,会得到编译错误;全局变量是允许声明但不使用的
  7. 如果想要交换两个变量的值,则可以简单地使用 a, b = b, a,两个变量的类型必须是相同
  8. 空白标识符 _ 是一个只写变量(被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃),你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

Go语言常量(在程序运行时,不会被修改的量)

1
2
3
4
5
6
7
const LENGTH int = 10

const ( // 常量用作枚举
Unknown = 0
Female = 1
Male = 2
)

  1. 常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过
  2. iota,特殊常量,可以认为是一个可以被编译器修改的常量

运算符

  1. & 返回变量存储地址
  2. * 指针变量(保存的是一个地址值)

条件判断语句

  1. if、if else、switch、select(select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行)
  2. 注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断

循环控制语句

  1. break、continue,还有个goto(将控制转移到被标记的语句)

函数

1
2
3
func function_name( [parameter list] ) [return_types] {
函数体
}

  1. 标准库函数有 len()

数组

1
2
// 不指定长度
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

指针

  1. 一个指针变量通常缩写为 ptr
  2. nil 指针称为空指针

结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

type Books struct {
title string
author string
subject string
book_id int
}


func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})

// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})

// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}

结构体指针

Go 语言切片(Slice)

  1. Go 语言切片是对数组的抽象。
  2. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    numbers := []int{0,1,2,3,4,5,6,7,8} // 初始化

    // 切片
    fmt.Println("numbers ==", numbers)
    fmt.Println("numbers[0] == ", numbers[0])
    fmt.Println("numbers[:2] == ", numbers[:2])
    fmt.Println("numbers[1:2] == ", numbers[1:2])

    // append()
    numbers = append(numbers, 2,3,4)

    // copy()
    copy(des, src)

    var identifier []type // 声明一个未指定大小的数组来定义切片
    slice1 := make([]type, len) // 用make()函数来创建切片
    make([]T, length, capacity) // 也可以指定容量,其中capacity为可选参数
  3. 切片是可索引的,并且可以由 len() 方法获取长度

  4. 切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少
  5. 一个切片在未初始化之前默认为 nil,长度为 0
  6. 切片截取,跟python差不多[lower-bound:upper-bound]

Go 语言范围(Range)

  1. range 关键字在数组和切片中返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值

Go 语言Map(集合)

  1. Map 是一种无序的键值对的集合

    1
    2
    3
    4
    5
    6

    /* map 关键字,声明变量,默认 map 是 nil */
    var map_variable map[key_data_type]value_data_type

    /* 使用 make 函数 */
    map_variable := make(map[key_data_type]value_data_type)
  2. 如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var countryCapitalMap map[string]string /*创建集合 */
    countryCapitalMap = make(map[string]string)

    /* map插入key - value对,各个国家对应的首都 */
    countryCapitalMap [ "France" ] = "巴黎"
    countryCapitalMap [ "Italy" ] = "罗马"
    countryCapitalMap [ "Japan" ] = "东京"
    countryCapitalMap [ "India " ] = "新德里"

    /* delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key */
    delete(countryCapitalMap, "France")

Go 语言递归就是调用自己,不知道后续是否有优化算法

Go 语言类型转换

1
type_name(expression)

Go 语言接口

  1. interface 是一种数据类型

Go 错误处理

Go 并发

  1. goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的,自行了解下 goroutine 与线程的区别

    1
    go 函数名( 参数列表 )
  2. 通道(channel)是用来传递数据的一个数据结构

    1
    ch := make(chan int)

开发工具

  1. LiteIDE、Eclipse(自行搜刮)