最近Go很火,尤其是协程,好像很厉害,特地来学一下。
为啥很火呢?
- 天生支持高并发
- 强大的标准库
- 标准库
- gc
- runtime
- 简单易学
基础语法
之前学习过java,所以和java对比着来
变量
- 局部变量
var a int //默认值是0
var b int = 10 //声明一个值,并初始化
var c = 100 //类型自动推断
d := 1000 //最常用 省去 var,并且类型自动匹配
- 全局变量
第四种不支持全局变量 - 多变量
- 单行写法
var xx,yy int = 100,200 var aa,bb = 100."100"
- 多行写法
var{ aa int = 100 bb bool =true }
- 单行写法
常量
const a int = 10
const {
a = 10
b = 20
}
//iota 每行 加1,从0开始
const{
a = 10*iota //0
b //10
c //20
}
函数
- 格式
func FuncName(a int ,b bool) (x int, y int){
...
return 1,true
}
-
init()
-
import
defer
类似Java的finally,最终执行,一般写在第一行。
指针
跟c一个道理
*和 &
数组
- 声明数组方式
var array [10]int
array := [10]int{1,2,3,4}
array :=[4]int{1,2,3,4}
- 重要的一点,go中数组是值类型!!作为形参传入函数时,会进行复制!!!
切片slice
*声明方式
其实是个动态数组
传参时是引用传递 !!!!
array := []int{1,2,3}
var slice int[]
slice = make([]int,3)
slice := make(int[],3)
底层还是数组
可以自动扩容。
map
声明方式
var map = map[string]string
map = make(map[string]string)
map := make(map[string]string)
//map 也是引用类型
面向对象特征
和java区别很大,go里面没有类之说,需要慢慢熟悉
封装
go的封装依靠结构体struct
//go 通过 首字母大小写来控制访问权限,大写表示对外可以访问,否则只能本包访问
type Hero struct{
Name string
Ad int
level int
}
//type 可以 封装成员变量 ,那方法呢?,如下:
// 通过 *Hero 和这个结构体绑定
func (Hero *Hero) Show(){
println("Name :",Hero.Name)
}
继承
和java 中的区别更大,这种感觉是用组合来模拟继承
type Human struct{
name string
sex string
}
type SuperMan struct{
Human
level int
}
var s SuperMan
s.name = "lisi"
s.sex = "male"
s.level = 18
多态
有几个前提:
- 有一个父类(接口)
type Animal interface{
Sleep()
GetColor()
GetType()
}
- 有子类(实现了父类的全部接口方法)
type Cat struct{
color string
}
func (this *Cat) Sleep(){
println("cat is sleeping")
}
func (this *Cat) GetColor() string{
return this.color
}
func (this *Cat) GetType() string{
return "CAt"
}
- 父类型的指针指向子类
var animal Animal
animal = &Cat{"Green"}
animal.Sleep() //调用的是cat的sleep方法,这就是多态。
并发编程
goroutine
开启goroutine很简单 关键字 :go
go func test(){
println("开启一个goroutine")
}
想要退出协程,则使用
runtime.Goexit() //退出当前的goroutine
channel
goroutine之间的通信方式,类似java 的阻塞队列
- 使用方式
make(chan Type)
make(chan Type,capacity)
channel <- value //发送value到channel
x:=<-channel //从channel中获取数据
x,ok :=<-channel //功能同上,同时检查通道是否关闭或者为空
- select
单流程下一个go只能监控一个channel状态,select可以完成监控多个channel的状态
类似IO多路复用
select{
case <-chan1:
//如果chan1有数据读,进行该case
case chan2<- 1:
//如果chan2写入数据,进行该case
default :
//都没有成功,则执行这里
}
- range
可以使用range来迭代channel
for data := range channel{
xxx
}
sync
sync包里提供了几种方法,用来控制并发
- waitGroup
类似java中的countdownlatch - mutex
互斥锁
*RWmutex
读写互斥锁,类似java中的读写锁(readwritelock)
rwlock.rlock(读加锁)
rwlock.runlock(读解锁) - once
某些操作只执行一次
sync.once
once.do(func()) - 并发安全的map
sync.map - atomic
原子操作
go module
没有go module之前,项目都得在gopath下,非常的奇葩的规定,除非规定多个 gopath(比如ide golang 每个项目 单独一个gopath)
有了 gomodule 任何路径都可以了,go init