标签:全局 lag next rate 断言 main 容量 链表 group
1 整型
分为int、uint,uint8
是byte
型,int16
对应C中的short型,int64
对应long型
2 特殊整型
uintptr 无符号整型,用于存放一个指针
3 浮点型
float32和float64
4 复数
complex64和complex128
5 byte和rune类型
uint8就是byte类型,代表ASCII码的一个字符,uint32就是rune类型,代表一个UTF字符
rune用来处理非英文,如汉语、日语
// 这样
func main() {
s := "二哈"
runes := []rune(s)
fmt.Println(string(runes))
}
// 或者这样
func main() {
s := "二哈"
bytes := []byte(s)
for len(bytes) > 0 {
ch, size := utf8.DecodeRune(bytes)
bytes = bytes[size:]
fmt.Printf("%c ", ch)
}
}
6 类型转换
var a, b = 3, 4
var c int
// math.Sqrt()接收的参数是float64类型,需要强制转换
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
7 bool类型
和其他语言一样
8 枚举
枚举使用iota
,这玩意默认值是0
,下面的默认值是1什么鬼?
const (
FlagNone = 1 << iota
FlagRed // iota=1 2 << iota
FlagGreen // iota=1 3 << iota
FlagBlue // iota=1 4 << iota
)
func main() {
fmt.Printf("%d %d %d %d\n", FlagNone, FlagRed, FlagGreen, FlagBlue)
}
// 2 4 8
package main
import (
"fmt"
)
type Byte float64
const (
_ = iota
KB Byte = 1 << (10*iota) //iota自动+1,此时值为2,即 1 << (10*2)
MB //表达式自动重复, 1 << (10*iota) 即 1 << (10*3)
GB //...
TB
PB
EB
ZB
YB
)
func (b Byte) String() string {
switch {
case b > YB:
return fmt.Sprintf("%.2fYB", b/YB)
case b > ZB:
return fmt.Sprintf("%.2fZB", b/ZB)
case b > EB:
return fmt.Sprintf("%.2fEB", b/EB)
case b > PB:
return fmt.Sprintf("%.2fPB", b/PB)
case b > TB:
return fmt.Sprintf("%.2fTB", b/TB)
case b > GB:
return fmt.Sprintf("%.2fGB", b/GB)
case b > MB:
return fmt.Sprintf("%.2fMB", b/MB)
case b > KB:
return fmt.Sprintf("%.2fKB", b/KB)
}
return fmt.Sprintf("%.2fB", b)
}
func main() {
var x Byte
x = 1024*1024*1024 * 15
fmt.Println(x)
x = 1024*1024*1024*1024*1024 * 42
fmt.Println(x)
}
//15.00GB
//42.00PB
package main
import "fmt"
const (
A, B int = iota, iota+1
_, _
C, D
E int = iota+10
)
func main() {
fmt.Println(A, B, C, D, E)
}
//0 1 2 3 13
9 指针
ptr := &v,v的类型为T,v代表被取地址的变量,ptr的类型为*T,*代表指针
列表是使用container/list包来实现的,内部原理是双向链表
1 初始化:
2 添加:
lst.PushBack("aaa") //尾部
lst.PushFront("bbb") // 头部
3 插入:
element := lst.PushBack("aaa") //尾部添加后保存元素句柄
lst.InsertAfter("111", element)
lst.InsertBefore("222", element)
4 删除:
lst.Remove(element)
5 遍历:
for i := lst.Front(); i != nil; i = i.Next() {fmt.println(i.value)}
1 定义:var a [3]int,定义一个长度为3元素类型为int的数组a,[3]int和[4]int类型不同
2 三种初始化:
3 两种遍历:
4 多维数组:
var b = [3][2]{{1, 2}, {3, 4}, {5, 6}}
var b = [...][2]{{1, 2}, {3, 4}, {5, 6}} //多维数组只有第一层可以使用...
来让编译器推导数组长度
1 定义:var a []int
2 初始化:
3 切片的长度和容量:len()、cap()
切片不能直接比较,合法比较是和nil做比较,判断是否为空,用len(a) == 0
3 遍历:for、for range
4 复制切片:
copy(),切片是应用类型,直接赋值拷贝,若是修改会改变原有切片,所以用copy
4 切片添加元素:
append()
a = append(a, element) // 添加一个元素
a = append(a, elements...) //添加多个元素
5 删除元素:
append(),没有特定的删除方法,还是用使用切片本身的特性
a = []int{1,2,3}
a = a[1:] // 删除开头1个元素 a = a[N:] // 删除开头N个元素 a = append(a[:0], a[1:]...) // 删除开头1个元素 a = append(a[:0], a[N:]...) // 删除开头N个元素
用 copy() 函数来删除开头的元素
a = a[:copy(a, a[1:])] // 删除开头1个元素 a = a[:copy(a, a[N:])] // 删除开头N个元素
a = append(a[:i], a[i+1:]...) // 删除中间1个元素 a = append(a[:i], a[i+N:]...) // 删除中间N个元素 a = a[:i+copy(a[i:], a[i+1:])] // 删除中间1个元素 a = a[:i+copy(a[i:], a[i+N:])] // 删除中间N个元素
a = a[:len(a)-1] // 删除尾部1个元素 a = a[:len(a)-N] // 删除尾部N个元素
多维切片同理
1 定义:map[key][value]==>map[int][int],类型变量默认为nil,要用make初始化才能使用
2 初始化:m := make(map[string][interface{}])
3 遍历:for range
4 删除键值对:
delete(m, key)
5 判断某个key是否存在:
value, ok := map[key],ok为true存在,false不存在
6 map不是线程安全的,并发使用sync.Map:
package main
import (
"fmt"
"sync"
)
func main() {
var scene sync.Map
// 将键值对保存到sync.Map
scene.Store("red", 1)
scene.Store("blue", 3)
scene.Store("green", 2)
// 从sync.Map中根据键取值
fmt.Println(scene.Load("red"))
// 根据键删除对应的键值对
scene.Delete("red")
// 遍历所有sync.Map中的键值对
scene.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}
1 自定义类型
type MyString string // 将MyString定义为string类型,MyString是一种新的类型,具有string的特性
2 类型别名
type byte = int8
type rune = int32 // byte和rune就是类型别名
3 类型定义和类型别名的区别
类型别名用=,结果还是原来类型,自定义类型不用=,结果是新定义的类型
4 结构体的定义
type 类型名 struct { 字段名 字段类型 字段名 字段类型 ... }
type Person struct {
name string
age int
}
5 结构体声明
var person Person
6 实例化
person.name = "gopher"
person.age = 18
7 匿名结构体
var p1 struct{Name string, Age int}
p1.Name = "erha"
p1.Age = 18
8 指针结构体
var p2 = new(Person)
P2.name = "gopher"
p2.age = 18
fmt.Printf("%T\n", p2) // *main. Person
fmt.Printf("p2=%#v\n", p2) // p2=&main.Person{name:"gopher", age:18}
9 取结构体的地址实例化
var p3 = &Person{}
P2.name = "erha"
p2.age = 18
10 结构体初始化
没有初始化的结构体,其成员变量都是对应类型的零值
p1 := Person {
name: "gopher"
age: 18
}
p1 := &Person {
name: "gopher"
age: 18
}
p2 := &Person {
"gopher"
18
}
这种必须初始所有字段、顺序必须不能改变、不能和键值初始化混用
11 构造函数
Go结构体没有构造函数,可以自己实现
func newPerson(name string, age int8) *Person {
return &person{
name: name,
age: age,
}
}
12 方法
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) { 函数体 }
//Study Person做梦的方法
func (p Person) Study() {
fmt.Printf("%s Go \n", p.name)
}
func (p *Person) SetAge(newAge int8) {
p.age = newAge
}
值类型接收者和指针类型接收者是有区别的
方法和函数的区别是,函数不属于任何类型,方法属于特定的类型
13 结构体的匿名字段
type Person struct {
string
int
}
14 嵌套结构体
//Address 地址结构体
type Address struct {
Province string
City string
}
//User 用户结构体
type User struct {
Name string
Gender string
Address Address
}
15 嵌套匿名结构体
//User 用户结构体
type User struct {
Name string
Gender string
Address
}
16 结构体的"继承"
就是组合
type Animal struct {
name string
}
type Dog struct {
Feet int8
*Animal //通过嵌套匿名结构体实现继承
}
17 结构体标签
type Person struct {
ID int `json:"id"` //通过指定tag实现json序列化该字段时的key
Name string //json序列化是默认使用字段名作为key
age string //私有不能被json包访问
}
1 接口类型
Go中接口是一种类型,一种抽象的类型
interface是一组method的集合,也就是一个需要实现的方法列表
2 接口的定义
type 接口类型名 interface {
方法名1(参数列表1) 返回值列表1
方法名2(参数列表2) 返回值列表2
}
3 实现接口的条件
一个对象只要全部实现了接口中的方法,就实现了这个接口
4 接口类型变量
type Writer interface {
write()
}
var w Writer // 声明一个Writer类型的变量w
5 值接收者和指针接收者
就是看传入结构体类型是值类型 还是 指针类型
type Mover interface {
move()
}
type dog struct {}
func (d dog) move() {
fmt.Println("erha")
}
func main() {
var x Mover
var erha = dog{} // 二哈是dog类型
x = erha // x可以接收dog类型
var za = &dog{} // 藏獒是*dog类型
x = za // x可以接收*dog类型
x.move()
}
func (d *dog) move() {
fmt.Println("zaza")
}
func main() {
var x Mover
var erha = dog{} // 二哈是dog类型
x = erha // x不可以接收dog类型
var za = &dog{} // 藏獒是*dog类型
x = za // x可以接收*dog类型
}
6 接口嵌套
// Sayer 接口
type Sayer interface {
say()
}
// Mover 接口
type Mover interface {
move()
}
// 接口嵌套
type animal interface {
Sayer
Mover
}
7 空接口
空接口定义:var a interface{}
空接口的应用:
8 类型断言
var a interface{}
v, ok := a.(string)
......
断言后可以使用switch
如 switch v := x.(type) {
case string:
......
default:
......
}
1 并发和并行
Erlang 之父 Joe Armstrong那张图:并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机,如果串行,一个队列使用一台咖啡机。并发和并行都可以是很多个线程,就看这些能不能同时被(多个)cpu执行,如果可以就说明是并行,而并发是多个线程被(一个)cpu轮流切换着执行。
2 goroutine
go并发使用goroutine(runtime)和channel
启动:go func() {...},启动多个用for循环
3 goroutine的调度
GPM是go运行时(runtime)层面的实现,是go自己实现的一套调度系统。
G就是个goroutine,里面除了存放goroutine信息外,还有与所在P的绑定信息
P管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境,P对自己管理goroutine进行调度,自己的队列消费没了就去全局队列取,全局队列也没了就去其他P队列抢任务。
M是go运行时对操作系统内核线程的虚拟,与内核线程一般是一一映射的关系,goroutine最终要放到M上执行。P与M一般也是一一对应的,P管理着一组G挂载在M上运行,一个G长期阻塞在M上时,runtime会新建一个M,阻塞G所在的P会把其他的G挂载到新建的M上,旧的G阻塞完成时,回收旧的M。
goroutine是运行时go自己的调度器调度,不需要os内核来调度,不涉及用户态和内核态切换。
go运行的调度器使用GOMAXPROCS
参数来确定需要使用多少个os线程来同时执行go代码,默认是cou核心数,可以通过runtime.GOMAXPROCS()
设置当前程序并发占用的cpu核心数。
3 channel
Go提倡通过通信共享内存而不是通过共享内存而实现通信。
channel定义:var 变量 chan 元素类型,例如var c chan int
channel创建:make(chan 元素类型, [缓冲区大小]),例如
c := make(chan int) // 无缓冲区
c := make(chan int, 1) // 有缓冲区
channel操作:
单向通道
4 select(从多个channel接收数据)
// 性能会很差
for {
// 从ch1接收值
v, ok := <-ch1
// 从ch2接收值
v, ok := <-ch2
…
}
select {
case <www.yuntianyul.com-ch1:
...
case v <- ch2:
...
case v2 :www.chuancenpt.com= ch3:
...
default:
...
}
如果多个case同时满足,select会随机选择一个;没有case的select会一直等待,用于阻塞main。
5 并发安全锁
互斥锁:sync.Mutex
读写互斥锁:sync.RWMutex
并发任务同步:sync,WaitGroup
wg *WaitGroup Add(www.feihongyul.cn),wg www.hongtuupt.cn *WaitGroup Done(),wg *WaitGroup Wait()
高并发任务只执行一次:sync.Once,只有一个Do方法,使用:
var one sync.Once
one.Do(func(www.yixingylzc.cn){www.jiuyueguojizc.cn })
还可以用来实现单例。
6 原子操作
sync/atomic
获取值的类型:reflect.TypeOf(www.baihua178.cn)
type定义的类型:x.Name(www.feishenbo.cn)
底层的类型:x.Kind(www.qiaoheibpt.com)
原始值:reflect.ValueOf(www.baishenjzc.cn)
结构体反射:x.NumField(www.yachengyl.cn) x.Field()
标签:全局 lag next rate 断言 main 容量 链表 group
原文地址:https://www.cnblogs.com/woshixiaowang/p/13532737.html