// 普通声明
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 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
- 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) // 关闭