- const、func、import、package、type和var用来声明各种代码元素。
- chan、interface、map和struct用做 一些组合类型的字面表示中。
- break、case、continue、default、else、fallthrough、for、goto、if、range、return、select和switch用在流程控制语句中。
- defer和go也可以看作是流程控制关键字, 但它们有一些特殊的作用。
- 关键字不能被用做标识符。
- _是一个特殊字符,它叫做空标识符
- 布尔类型:bool。
- 11种内置整数类型:int8、uint8、int16、uint16、int32、uint32、int64、uint64、int、uint和uintptr。
- 两种内置浮点数类型:float32和float64。
- 两种内置复数类型:complex64和complex128。
- 一种内置字符串类型:string。
- 指针类型 - 类C指针 // *T
- 结构体类型 - 类C结构体
type T struct {
type string
}
- 函数类型 - 函数类型在Go中是一种一等公民类别
func(int) (bool, string)
- 容器类型
数组类型 - 定长容器类型
[5]T // 一个元素类型为T、元素个数为5的数组类型
切片类型 - 动态长度和容量容器类型
[]T // 一个元素类型为T的切片类型
映射类型(map)- 也常称为字典类型。在标准编译器中映射是使用哈希表实现的。
map[Tkey]T // 一个键值类型为Tkey、元素类型为T的映射类型
- 通道类型 - 通道用来同步并发的协程
chan T
chan<- T
<-chan T
- 接口类型 - 接口在反射和多态中发挥着重要角色
interface {
Method0(string) int
Method1() (int, bool)
}
- byte是uint8的内置别名。 我们可以将byte和uint8看作是同一个类型
- rune是int32的内置别名。 我们可以将rune和int32看作是同一个类型。
- iota是Go中预声明(内置)的一个特殊的有名常量。自增。 iota被预声明为0,但是它的值在编译阶段并非恒定。 当此预声明的iota出现在一个常量声明中的时候,它的值在第n个常量描述中的值为n(从0开始)。 所以iota只对含有多个常量描述的常量声明有意义。
- import 下划线:当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。
- _下划线在代码中:忽略返回值(一般是错误值);占位符;接口断言;函数中省略参数名;引入包执行init();
string(65) // "A"
string('A') // "A"
string('\u68ee') // "森"
string(-1) // "\uFFFD"
string(0xFFFD) // "\uFFFD"
string(0x2FFFFFFFF) // "\uFFFD"
- 两个类型不一样的基本类型值是不能相互赋值的, 我们必须使用显式类型转换将一个值转换为另一个值的类型之后才能进行赋值。
const k int16 = 255
var n = k //
var f = uint8(k + 1) // error 常量数字值的类型转换不能溢出
var h = uint8(n + 1) // 0 非常量可溢出
- %v:将被替换为对应实参字符串表示形式。
- %T:将替换为对应实参的类型的字符串表示形式。
- %x:将替换为对应实参的十六进制表示。实参的类型必须为整数,整数数组(array)或者整数切片(slice)等。
- %s:将被替换为对应实参的字符串表示形式。实参的类型必须为字符串或者字节切片(byte slice)类型。
- %%:将被替换为一个百分号。
- switch-case:fallthrough关键字可以直接跳到下一个代码块
- 对于for/select/switch,Label必须紧挨着他们
func FindSmallestPrimeLargerThan(n int) int {
Outer:
for n++; ; n++{
for i := 2; ; i++ {
switch {
case i * i > n:
break Outer //结束循环,跳到return n
case n % i == 0:
continue Outer//结束当前的执行,跳回for
}
}
}
return n
}
- 协程也被称为绿色线程。绿色线程是由程序的运行时(runtime)维护的线程。一个绿色线程的开销(比如内存消耗和情景转换)比一个系统线程常常小得多。
- Go不支持创建系统线程,所以协程是一个Go程序内部唯一的并发实现方式。
- 查询当前程序可利用的逻辑CPU数目:runtime.NumCPU()
- 获取和设置逻辑处理器的的数量:runtime.GOMAXPROCS()
- Add方法用来注册新的需要完成的任务数。
- Done方法用来通知某个任务已经完成了。
- 一个Wait方法调用将阻塞(等待)到所有任务都已经完成之后才继续执行其后的语句。
- M - worker thread, or machine. 工作线程 (线程)
- P - processor, 执行Go代码时所必须的一种资源。(逻辑处理)
- G - goroutinue. 协程
P(逻辑处理器) 会讲将不同的处于运行状态的**G(协程)交给不同的M(线程)**来执行
- 一个延迟调用可以修改包含此延迟调用的最内层函数的返回值
func Triple(n int) (r int) {
defer func() {
r += n // 修改返回值
fmt.Println("1", r)
fmt.Println("3", n)
}()
fmt.Println("2", n)
return n + n // r = n + n
}
func main() {
fmt.Println(Triple(5)) //15
}
- 一个匿名函数体内的表达式是在此函数被执行的时候才会被逐个估值的,不管此函数是被普通调用还是延迟/协程调用。
package main
import "fmt"
func main() {
func() {
for i := 0; i < 3; i++ {
defer fmt.Println("a:", i)
}
}() //210
fmt.Println()
func() {
for i := 0; i < 3; i++ {
defer func() {
fmt.Println("b:", i)
}()
}
}() //333
}
- log标准库中的打印函数是经过了同步处理,fmt标准库中的打印函数没有被同步