# 特点
# 语言特征
- 类C语言
- 强类型
- 强制语法
# 语言优点
- 语法简练
- 标准库较多
- 部署简单
- 可自动推导类型
- 拥有GC
- Goroutines
- Channels
- Defer
# 语言缺点
- 语法怪异
- 第三方库较少
- 错误处理简单
- 缺少枚举
# 语法
# 数据类型
- 布尔型:bool
- 有符整型:int, int8(byte), int16, int32(rune), int64
- 无符整型:uint, uint8, uint16, uint32, uint64, uintptr
- 浮点型:float32, float64
- 复数型:complex64, complex128
- 字符串型:string
# 运算符
| 类型 | 运算符 | 结合性 |
|---|---|---|
| 逗号运算符 | , | >> |
| 赋值运算符 | =、+=、-=、*=、/=、 %=、 >=、 <<=、&=、^=、|= | << |
| 逻辑或 | || | >> |
| 逻辑与 | && | >> |
| 按位或 | | | >> |
| 按位异或 | ^ | >> |
| 按位与 | & | >> |
| 相等/不等 | ==、!= | >> |
| 关系运算符 | <、<=、>、>= | >> |
| 位移运算符 | <<、>> | >> |
| 加法/减法 | +、- | >> |
| 乘法/除法/取余 | *(乘号)、/、% | >> |
| 单目运算符 | !、*(指针)、& 、++、–、+(正号)、-(负号) | << |
| 后缀运算符 | ( )、[ ]、-> | >> |
# 变量声明与赋值
// 普通声明
var a int // a == 0
var a float // a == 0.0
var a bool // a == false
var a string // a == ""
var a *int // a == nil
var a, b int // a == 0, b == 0
// 普通声明并赋值
var a int = 1 // a == 1
var b = 1 // b == 1
var a, b = 1, 2 // a == 1, b == 2
// 推导声明并赋值
a := 1 // a == 1
a, b := 1, 2 // a == 1, b == 2
// 批量声
var (
a int
b float
c struct {
d bool
}
) // a == 0, b == 0.0, d == false
// 匿名变量
_, a = 1, 2 // a == 2
# 变量作用域
package main
a := 1 // 全局变量
func main() {
b := 1 // 局部变量
}
# 常量
const a int = 1 // a == 1
const a = 1 // a == 1
const (
a = 1 // a == 1
b = 1.1 // b == 1.1
)
- 常量类型只为基础类型
- 常量需要在编译时确定
- 常量可以用作数组长度
- 推导声明会产生无类型常量
- 无类型常量通用于子基础类型
# 类型定义与别名
type Long int32 // Long
type Int32 = int32 // int32
# 注释、关键字和标识符
# 注释
// 单行
/*
多行
*/
# 关键字
- var, const, type
- if, else, switch, case, default, fallthrough
- for, goto
- break, continue
- map, range, chan, select, go
- import, package
- func, return, defer
- struct, interface
# 标识符规则
- 由英文字母、数字、下划线组成
- 严格区分大小写
- 不能以数字开头
- 不能包含空格
- 不能是关键字
- 不能是标准库包名
- 建议使用驼峰命名法
- 大写开头是Public
- 小写开头是Private
# 预定义标识符
- bool
- int, int8, int16, int32, int64, byte, rune
- uint, uint8, uint16, uint32, uint64, uintptr
- float32, float64
- complex, complex64, complex128
- string
- false, true, nil, iota
- new, make
- copy, append, delete
- len, cap
- close, recover, panic
- print, println
- real, imag
# nil
- nil 没有类型
- nil 不能比较
- nil 地址为 0x0
- nil 为指针、容器、通道、函数、接口的空值
- nil 所占空间与类型一致
# 逻辑
# if else
if true {
// codes
}
if true {
// codes
} else {
// codes
}
if true {
// codes
} else if false {
// codes
} else {
// codes
}
if b = false; b {
// codes
}
# switch case
a := 1
switch a {
case 1:
// codes
case 2:
// codes
default:
// codes
}
switch {
case a > 0:
// codes
}
switch a {
case 1:
// codes
fallthrough
case 2:
// codes
fallthrough
default:
// codes
}
# for
for {
// codes
}
for true {
// codes
}
for i := 0; i < 5; i++ {
// codes
}
i := 0
for ; i < 5; i++ {
// codes
}
i := 0
for ; ; i++ {
// codes
}
for key, val := range "123" {
// codes
}
for key, val := range []int{1, 2, 3} {
// codes
}
for key, val := range map[int]string{1:"a", 2:"b"} {
// codes
}
a := make(chan int)
a <- 1
a <- 2
for val := range a {
// codes
}
# goto
test:
// codes
goto test
# break / continue
for {
break
}
for {
continue
}
# 容器
# 数组
var a [2]int // a == [0, 0]
var b = [3]int{1, 2} // b == [1, 2, 0]
c := [...]int{1, 2, 3} // c == [1, 2, 3]
var d [2][2]int // d == [[0, 0], [0, 0]]
e := [2][2]int{{1}, {1:2}} // e == [[1, 0], [0, 2]]
# 切片
var a []int // a == []
var b = []int{} // b == []
c := []int{1, 2}[0:0] // c == []
d := []int{1, 2}[:] // d == [1, 2]
e := make([]int, 2, 5) // e == [] len(e) == 2 cap(e) == 5
f := append([]int{}, 1) // f == [1]
g := append([]int{}, 1, 2) // g == [1, 2]
h := append([]int{}, []int{1, 2, 3}...) // h == [1, 2, 3]
i := append([]int{0, 1}, []int{2, 3}...) // i == [0, 1, 2, 3]
j := append([]int{0}, append([]int{1}, []int{2}...)...) // j == [0, 1, 2]
k := []int{1, 2, 3}[1:] // k == [2, 3]
l := []int{1, 2, 3}[:2] // l == [1, 2]
m := append([]int{1, 2, 3}[:1], []int{1, 2, 3}[2:]...) // m == [1, 3]
# Map
var a map[int]string // a == {}
b := make(map[int]string , 100) // b == {}
c := map[int]string{1: "a", 2: "b"} // c == {1: "a", 2: "b"}
delete(map[int]string{1: "c", 2: "d"}, 1) // "map" == {2: "d"}
# 函数
# 声明
func a(i int, j int) int { return i + j } // a(1, 2) == 3
b := func(i int, j int) int { return i + j } // b(1, 2) == 3
c := func(i int, j int) int { return i + j }(1, 2) // c == 3
d := func(i ...int) int { return len(i) }(0, 1) // d == 2
# defer
fmt.Println(0)
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
// 0
// 3
// 2
// 1
# panic
panic("error")
// panic: error
# recover
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
}
}()
fmt.Println(1)
panic(2)
fmt.Println(3)
// 1
// 2
# 结构体
# 声明
type A struct {
B int
C string
}
var a A // a == {0, ""}
b := A{1, "2"} // b == {1, "2"}
c := new(A) // c == &{0, ""}
d := &A{} // d == &{0, ""}
e := &A{1, "2"} // e == &{1, "2"}
a := struct {
B int
C string
}{1, "2"} // f == {1, "2"}
# 访问控制
package A
type A struct {
B int
b int
}
package B
a := A{}
a.B = 1 // success
a.b = 1 // error
# 嵌入
type A struct {
B int
C string
}
type D struct {
A
E int
F string
}
d := D{A{1, "2"}, 3, "4"} // d == {{1, '2'}, 3, '4'}
d.A.b = 2 // d == {{2, '2'}, 3, '4'}
d.b = 3 // d == {{3, '2'}, 3, '4'}
# 成员方法
type A struct {
b int
}
func (a *A) plus() {
a.b += 1
}
a := A.A{}
a.plus() // a == {1}
# 接口
# 声明
type A interface {
b(int) int
}
var a A
# 实现
type A interface {
set(int)
}
type B interface {
get() int
}
type C struct {
D int
}
func (c *C) set(n int) {
c.D = n
}
func (c *C) get() int {
return c.D
}
c := new(C) // c == &{}
var a A // a == nil
a = c // a == &{}
a.set(1) // a == &{1}
var b B // b == nil
b = c // b == &{1}
n = b.get() // n == 1
# 空接口
var a interface{} // a == nil
a = 1 // a == 1
a = 0.1 // a == 0.1
b, ok := a.(int) // b == 0, ok = false
# 包
# 导入
import "a" // 单行导入
import ( // 多行导入
"b" // 绝对路径 "GOPATH/src/"
"./c" // 相对路径
E "e" // 别名引用
. "f" // 省略引用
_ "g" // 匿名引用
)
# 自定义
- a
-- a.go
package a
type A struct {
B int
}
func NewA(n int) *A {
return &A{B: n}
}
func (a *A) SetB(n int) {
a.B = n
}
func (a *A) GetB() int {
return a.B
}
- main
-- main.go
package main
import (
"./a"
)
func main() {
a := a.NewA(1) // a.B == 1
}
# 多线程
# Goroutine
f := func(n int) {
n += 1
}
go f(1) // n == 2
go func(n int) {
n += 1
}(1) // n == 2
# Channel
var a chan int
var b chan<- int
var c <-chan int
d := make(chan int) // 双向
e := make(chan<- int) // 单入向
f := make(<-chan int) // 单出向
g := make(chan int, 0) // 阻塞
h := make(chan int, 100) // 填满前不阻塞
ch <- 1 // 写入
c := <-ch // 读出
d, ok := <-ch // 强制读出
<-ch // 丢弃读出
close(c) // 关闭
# 常用技巧
# 类型转换
int, err := strconv.Atoi("0")
int64, err := strconv.ParseInt("0", 10, 64)
string := strconv.Itoa(0)
string := strconv.FormatInt(0, 10)
# 时间戳
t1 := time.Now().Unix() // 秒级时间戳
t2 := time.Now().UnixNano()/1e6 // 毫秒级时间戳
t3 := time.Now().UnixNano() // 纳秒级时间戳
# 添加代理
$ go env # 查询配置
$ go env -json # 查询配置以Json形式
$ go env -w GO111MODULE=on # 开启
$ go env -w GOPROXY=[url],direct # 设置
$ go env -u GOPROXY # 取消
# 常用镜像
https://goproxy.cn/
https://goproxy.io/
https://mirrors.aliyun.com/goproxy/
# Map中Key值是否存在
var value, ok = demo["key"]
# Base64加密解密
var str = base64.StdEncoding.EncodeToString([]byte(""))
var bytes, err = base64.StdEncoding.DecodeString("")
# 计划
- *常用命令
- *字符串
- *指针
- *select
- *类型转换
- *包管理
- *泛型
- 堆栈
- iota 常量生成器
- godoc工具
- 容器的线程安全
- make和new的区别
- 函数递归
- 函数闭包
- 测试
- 结构体比较
- I/O操作
- 锁(乐观、悲观、互斥、死活)
- 多核优化
- 反射注入
- 文件操作
- 常用包
- sync.WaitGroup
- container/list
- container/ring
# 参考
版权协议

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.