Go 是一款编译型,强类型语言。node
GO
变量这一区域,借助于Js
lua
C
系列的合体。golang
nil
默认值,string
是值类型。类型 | 解释 | 备注 |
---|---|---|
uint8 |
无符号整型 | 位数 8,16,32,64 |
int8 |
有符号整型 | 位数 8,16,32,64 |
float32 |
浮点数 | 位数 32,64 |
complex64 |
复数 | 位数 64,128 |
经常使用 | 标识 | 大小 |
---|---|---|
字节 | byte |
1 字节 |
布尔 | bool |
1 字节 |
整形 | int , uint |
8 字节, 64位 |
指针 | uintptr |
8 字节, 64位,(uint ) |
字符串 | string |
16 字节 |
Js var const
在此处做用相同。lua _
以及栈式赋值,以及栈式返回,在此处亦有相同的做用。Go
变量类型可强限定,亦可动态限定,但只要被肯定一次即不可更改(本质上仍是强限定)。Go
变量动态限定类型仅可在局部函数内部使用,且全部Go
变量必须使用才可编译经过。// 常量强限定 const num int = 100; // 常量动态限定,仅限于第一次 const num = 100; // 变量强限定 var num int = 120; // 变量动态限定,仅限于第一次 var cnt = 100; // 强限定,栈式赋值 var num, cnt int = 100, 120; // 动态限定,栈式赋值 var num, str = 120, "stack"; // 虚变量 _, b int = demo(); // 语法糖 var num = 120; num := 120; // iota 特殊编译器行数变量
Go
语言的运算符继承了C,且保留了指针。运算符 | 经常使用 | 备注 |
---|---|---|
算术 | + - * / % ++ -- |
/ 整除运算 |
比较 | > >= < <= == != |
|
逻辑 | && || ! |
默认短路,复合! 要加() |
位 | & | ^ << >> |
某些算法中,位运算很重要 |
赋值 | = := ... |
赋值运算也是大同小异 |
指针 | &a 获取a的地址 *a 定义指针 |
& * 操做指针 |
// if-then if (true) { //TODO } // if-else if (true) { //TODO } else { //TODO } // switch val语句 switch (val) { case 0: // case 执行完即会退出 default: } // switch 语句 switch { case true: // case 执行完成即退出 case true: default: } // go 中 switch属于选择语句,即默认只会选中一项 switch { case true: fallthrough // 此处 case 执行完后,直接执行下一条case(跳过判断) default: } // for 语句实现循环 for { //TODO }
// 默认无返回值函数 func demo() { //TODO } // 单值返回 func demo() int{ //TODO return 0 } // 栈式返回 func demo() (int, int){ //TODO return 0,1 } // 函数传参类型 func demo(num int, cnt int){ //TODO } // defer 语句块,就至关于 finally 语句块,函数最终必需要执行此方法 func demo() { defer //TODO //TODO }
// 声明集合,此时为 nil 值,即不可以使用状态 var m = map[string] string // 建立集合,此出事后才可以使用 m = make(map[string] string) // 此处是将前面两步合在一块儿执行 var mk = make(map[int] int) // 经常使用方法 delete(mk, "str"); // 迭代集合 for k, v := range mk { // k, v }
C
系列的数组。// 新建数组变量 var cnt[10] int32; // 默认初始化 var cnt = [2] int32{1,2}; // 自动肯定长度的数组 var cnt = [...] int32 {1,2,3,4,5,6,7,}; // 函数传递数组 func demo(arr int[], size int){ // TODO } // 基于 arr生成切片,内存共享 var tmp = arr[1:]; len(tmp); // 数组长度,通常指切片数组或原始数组的大小,操做 idx 区间最大值 cap(tmp); // 数组底层大小,通常指原始数组长度 // 经常使用的一些方法 append(); copy(); // 迭代数组 for v := range arr{ // v }
Go
string 是一个基本类型,而非引用类型。Go
string 默认为UTF-8
编码,unicode
须要额外转码。"str"
表示,内部可转义,不可多行。`str`
表示,内部不可转义,能够多行。// 定义并初始化字符串 var str string = "123456"; // 常见字符串拼接 var add = str + "789"; // 字符串,切片 var cut = str[2:]; len(str); // 获取string,字节占用大小 str[0]; // 获取字节索引的 ASCII 数值
package
。.go
就是一个模块,module
。main/main.go => main()
。package main // 任何go程序,必须有 main 包,内部必须存在 main方法 import ( "fmt" // 标准库 IO ) // 引入多个包 import ( . "fmt" // 调用此模块下方法,无需前置 fmt tm "time" // 修改模块别名 tm _ "sync" // 执行一次 sync.init() 内部方法不可调用 ) // 任意模块文件被引用或加载时会执行一次 func init() { fmt.Println("当前文件加载时,会执行一次!") } // 程序主入口 func main() { fmt.Println("程序启动入口,必须存在!") } // go 的语法风格,会在行尾自动补齐 ;
待补充。算法
# 编译 demo 并执行 go run ./demo.go # 编译 demo 为可执行文件 run go build -o run ./demo.go
C
系列。// 这里通常都须要注释,否则会提示 type Atk struct{ idx int val int32 nam string } // 新建结构体,固定位置填充 var atk = Atk{1, 2, "hello"} // 新建结构体,索引位置填充,不索引时,以默认值填充 var atk = Atk{idx:1, val:2} // 新建结构体,初始化默认值,并返回一个指针 var ptr = new(Atk) ptr.idx, ptr.val, ptr.nam // 标准指针访问过程
Go
的接口就是Java
中接口以及实现类的一个衍生方式。// 定义接口 type Abs interface{ // Obj 访问 Name() string // *Obj 访问 name() string } // 定义结构体 type Obj struct{ idx int nam string } // 绑定 Obj 结构体,Name方法 func (e Obj) Name() string{ return e.nam } // 绑定 *Obj 结构体,Name方法 func (e *Obj) name() string{ e.nam = e.name + "tl" return e.nam } var obj = Object{1, "zsh"} var ptr = &obj // 指针以及非指针,传参不一样,故用法不一样 obj.Name() ptr.name()
Go
的异常处理机制基本类似于Java C
等语言。// 内置异常接口 type error interface{ Error() string } // 测试结构体 type Obj struct{ idx int val string } // 预约义返回错误的方法 func logError(e Obj) error{ if(e.idx == 0){ errors.New("idx == 0") } errors.New("ok") } func main(){ var obj = Obj{0, 1} // 输出预约义异常 fmt.Println(logError(obj)) } // golang - 通用性异常处理方式 func demo(){ defer func(){ var err = recover() // 捕获异常 }() // 匿名函数 panic("throws-errors!") // 抛出异常 }
Java
中的线程使用的是OS
级别的资源,而此处携程使用的是虚拟机
资源。OS
线程,并行处理,但切换上下文消耗资源,且自己的异步控制也较为复杂。虚拟机
线程,伪并行处理,不存在上下文切换,自己不会产生过多的异步控制逻辑。// 开启携程,返回值会被抛弃,伪并行 func demo() { var cnt = 0 for i := 0; i < 1000; i++ { // go 启动携程 go func(){ cnt++ }() } fmt.Println("cnt", cnt) } // 并发的锁控制,代码控制并发,简单高效 var cnt = 0 func demo(lock *sync.Mutex) { lock.Lock() cnt++ fmt.Println("cnt", cnt) lock.Unlock() } func main() { var lock = &sync.Mutex{} for i:=0; i < 50; i++ { go demo(lock) } for { lock.Lock() tmp := cnt lock.Unlock() // 让出时间片 runtime.Gosched() // 退出循环 if (tmp == 50) { break } } }
MQ
。// 无缓冲通道 var ch = make(chan int) ch <- 123 // 向 ch 通道发送数据,无返回值 var dat, ok = <-ch // 从 ch 通道取出数据,双返回值 // 缓冲通道,数据量超过阈值则发生阻塞 var ch = make(chan int, 10) close(ch) // 关闭通道,通道被关闭后,即不可以使用 // demo =====> var ch = make(chan int, 2) go func(){ ch <- 1 time.Sleep(time.Second) ch <- 2 time.Sleep(time.Second) close(ch) fmt.Println("ch - closed") }() for i := 0; i < 4; i++ { var dat, ok = <-ch fmt.Println(ok, dat) } /* true 1 true 1 ch - closed false 0 false 0 */
node
的异步设计。// 迭代型 for-range var ch = make(chan int) go func(){ for i := 0; i < 4; i++ { ch <- i fmt.Println("sending", i) time.Sleep(time.Second) } close(ch) }() for i := range ch { fmt.Println("receive", i) } fmt.Println("ending") // 选择型 select var ch1 = make(chan int) var ch2 = make(chan int) go func(){ ch1 <- 123 close(ch1) }() go func(){ ch2 <- 456 close(ch2) }() // 单选退出 select { case i := <-ch1: fmt.Println("ch1", i) case i := <-ch2: fmt.Println("ch2", i) default: fmt.Println("default") } // time 内置的时间触发器,内部就是个 chan var ch = time.NewTicker(time.Second) for t := range ch.C { fmt.Println(t) }