**本章节内容来自《菜鸟教程》,并经过整理后记录**
导航
---
[TOC]
---
### 数据类型
- 布尔型
- 数字类型
- 字符串类型
- 派生类型
- 指针类型
- 数组类型
- 结构化类型
- Channel类型
- 函数类型
- 切片类型
- 接口类型
- Map类型
---
### 变量
- 全局变量允许声明而不使用,但是局部变量声明则必须使用
```
var identifier type
# 例如
var a int
a = 1
b := 2
fmt.Println(a, b)
```
```go
package main
var (
x int
y bool
)
func main() {
var a, b int
c := "shayvmo"
fmt.Println(a, b, c, x, y)
}
// 输出
0 0 shayvmo 0 false
```
---
### 常量
```
const identifier [type] = value
// 显式类型定义
const a string = "abc"
// 隐式类型定义
const b = 4
```
#### iota
> iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)
```
package main
func main() {
const (
a = iota
b
c
d = "ha"
e
f = 100
g
h = iota
i
)
fmt.Println(a, b, c, d, e, f, g, h, i)
}
```
---
### 位运算符
- `&` 按位与
- `|` 按位或
- `^` 按位异或
- `>>` 右移 右移n位,相当于是除以2的n次方
- `<<` 左移 左移n位,相当于是乘以2的n次方
---
### 条件语句
switch: 默认每个case都有break操作,只要匹配到了,则不再匹配。如果需要执行后面的case,可以使用 fallthrough
```
switch a {
case 1:
fmt.Println("a匹配上了1")
fallthrough
case 2:
fmt.Printf("a虽然匹配上了1,加上fallthrough也能执行下面的case")
default:
fmt.Println("default")
}
```
---
### 循环语句
```
for [init]; condition; [post] {}
# 例如
for i := 0; i < 10; i++ {}
i := 1;
for ; i < 10; {
i += i * 2
}
```
---
### 函数
```
func function_name([params_list]) [return_type] {
函数体
}
```
#### 函数的参数
- 值传递(默认)
- 引用传递
#### 函数用法
- 函数作为另一个函数的实参
- 闭包
- 方法
```
package main
import (
"fmt"
"strconv"
)
// 函数类型变量
type callBack func(int)
func main() {
callBackTest(2, func(i int) {
fmt.Println("回调的函数:" + strconv.Itoa(i))
})
}
func callBackTest(x int, f callBack) {
f(x)
}
```
---
### 变量作用域
- 全局
- 局部
- 形式参数
---
### 数组
```
# 声明数组
var varible_name [size] varible_type
# 长度为10的整型数组
var a [10] int
```
初始化数组
```
# 初始化
var a = [...]int{1,2,3,4,5}
# 或
a := [...]int{2,24,42,3}
```
---
### 指针
```
# 声明格式
var var_name *var_type
# 执行int类型的指针 a1
var a1 *int
```
---
### 结构体
```
type struct_varible_type struct {
member definition
...
member definition
}
# 初始化
variable_name := structure_variable_type {value1, value2...valuen}
# 或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
```
例如
```
package main
type Book struct {
title string
author string
book_id int
}
func main() {
var book1 Book
book1.title = "何以笙箫默"
book1.author = "顾漫"
book1.bookId = 123
}
```
#### 结构体指针
```
var struct_pointer *Book
var book1Pointer *Book
book1Pointer = &book1
fmt.Printf("%p\n", book1Pointer)
# 何以笙箫默
book1Pointer.title
```
---
### 切片
```
var identifier []type
func main() {
arr := [...]int{1,2,3}
var slice = make([]int, 5)
slice1 := make([]int, 5)
slice2 := []int {0,1,2,3,4,5,6,7}
slice3 := arr[1:]
fmt.Println(slice, slice1, slice2, slice3)
slice2 = append(slice2, 8)
slice4 := make([]int, len(slice2), cap(slice2) * 2)
copy(slice4, slice2)
printSlice(slice2)
printSlice(slice4)
fmt.Printf("slice2[1:4] = %v", slice2[1:4])
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d value=%v\n", len(x), cap(x), x)
}
```
#### append 和 copy
append 向切片添加元素
- 当 append 一个满的切片时,最大长度会自动扩容,并且扩容到当前cap的2倍
copy 复制原切片到新的切片(如果需要扩容时,需要先创建一个cap更大的切片,再把原切片复制过去)
---
### 范围Range
- 用于for循环中迭代数组(array),切片(slice),通道(channel),集合(map)的元素。
- 在数组和切片中返回索引和索引对应的值,在集合中返回key-value对
```
func testRange() {
nums := [...]int{3,4,5,2}
for _, v := range nums {
fmt.Println(v)
}
maps := map[string]string{"a": "apple", "b": "banana"}
for k, v := range maps {
fmt.Printf("key: %s value: %s\n",k ,v)
}
// 第一个是字符的索引,第二个是字符的Unicode值
for k, v := range "abcdefg" {
fmt.Printf("%d -> %d", k, v)
}
}
```
---
### Map集合
- 无序的键值对集合
#### 定义Map
```
var map_varible map[key_data_type]value_data_type
map_varible := make(map[key_data_type]value_data_type)
func testMap() {
map1 := make(map[string]string)
map1["a"] = "apple"
for k, v := range map1 {
fmt.Printf("%s -> %s\n", k, v)
}
// has 可以判断集合中是否含有这个元素
value, has := map1["a"]
fmt.Println(value, has)
}
```
delete() 函数
```
func delete(m map[Type]Type1, key Type)
delete(map1, "a")
```
---
### 接口
```
// 定义接口
type interface_name interface {
method_name1 [return_type]
}
// 定义结构体
type struct_name struct {
title string
}
// 实现接口方法
func (struct_name_varible struct_name) method_name1() [return_type] {
}
```
**实例**
```
package main
import "fmt"
type Phone interface {
call()
number() string
}
type NokiaPhone struct {
}
type Iphone struct {
}
func (nokiaPhone NokiaPhone) call() {
fmt.Println("Nokia")
}
func (iphone Iphone) call() {
fmt.Println("iphone")
}
func (nokiaPhone NokiaPhone) number() string {
return "nokia-phone-135478"
}
func (iphone Iphone) number() string {
return "iphone-13123"
}
func main() {
testInterface()
}
func testInterface() {
var phone Phone
phone = new(NokiaPhone)
phone.call()
fmt.Println(phone.number())
phone = new(Iphone)
phone.call()
fmt.Println(phone.number())
}
```
---
### 错误处理
```
type error interface {
Error() string
}
func testError(a int,b int) (int, error) {
if b == 0 {
return 0, errors.New("除数不能为0")
}
return a / b, nil
}
```
---
### 并发 goroutine
```
go 函数名( 参数列表 )
```
**通道channel**
> 用于传递数据的一个数据结构。操作符 <- 指定通道方向,发送或接收。未指定方向则是双向通道
```
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <- c, <- c
fmt.Println(x, y, x + y)
}
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum
}
```
**通道缓冲区**
- 第二个参数是缓冲区的大小
```
ch := make(chan int, 100)
```
**遍历通道与关闭通道**
range 遍历通道时,如果通道没有关闭,会一直阻塞等到通道,这时需要主动关闭通道
```
v, ok := <-ch
```