golang 基础

Go

Go 是一款编译型,强类型语言。node

基础

变量

GO 变量这一区域,借助于 Js lua C 系列的合体。golang

  1. 全部变量都是强类型限定。
  2. 值类型变量皆存在非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 字节
  • 特性
  1. Js var const在此处做用相同。
  2. lua _ 以及栈式赋值,以及栈式返回,在此处亦有相同的做用。
  3. Go 变量类型可强限定,亦可动态限定,但只要被肯定一次即不可更改(本质上仍是强限定)。
  4. 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 特殊编译器行数变量

流程控制

  • 运算符
  1. 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
}
  • 函数
  1. 函数支持多值返回。
  2. 全部参数都执行值传递过程。
  3. 函数支持返回函数,也支持参数为函数。
// 默认无返回值函数
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
}
  • 数组
  1. 强内存、强类型限定的数组。
  2. 数组类型是兼容于 C 系列的数组。
  3. 数组的切片类型执行引用复制,不会从新复制内存。
// 新建数组变量
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
}
  • 字符串
  1. Go string 是一个基本类型,而非引用类型。
  2. Go string 默认为UTF-8编码,unicode须要额外转码。
  3. 通常用,"str"表示,内部可转义,不可多行。
  4. 特殊时,`str`表示,内部不可转义,能够多行。
// 定义并初始化字符串
var str string = "123456";

// 常见字符串拼接
var add = str + "789";

// 字符串,切片
var cut = str[2:];

len(str); // 获取string,字节占用大小
str[0]; // 获取字节索引的 ASCII 数值

特性

模块化

  • package
  1. 一个文件夹就是一个包,package
  2. 一个文件.go就是一个模块,module
  3. 程序主入口是个特殊的类型 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 的语法风格,会在行尾自动补齐 ;
  • module

待补充。算法

 
  • execute
# 编译 demo 并执行
go run ./demo.go

# 编译 demo 为可执行文件 run
go build -o run ./demo.go

抽象化

  • 结构体
  1. 结构体部分主要继承自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 // 标准指针访问过程
  • 接口
  1. Go的接口就是Java中接口以及实现类的一个衍生方式。
  2. 其本质上就是根据的结构体(实体),绑定不一样的处理方法。
// 定义接口
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()
  • error
  1. 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!") // 抛出异常
}

并发控制

  • 携程
  1. Java 中的线程使用的是OS级别的资源,而此处携程使用的是虚拟机资源。
  2. OS线程,并行处理,但切换上下文消耗资源,且自己的异步控制也较为复杂。
  3. 虚拟机线程,伪并行处理,不存在上下文切换,自己不会产生过多的异步控制逻辑。
// 开启携程,返回值会被抛弃,伪并行
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
        }
    }
}
  • 通道
  1. 通道是一种在不一样线程之间传递数据的机制,核心机制相似 MQ
  2. 通道仅支持不一样线程之间的数据交互,单线程会发生死锁,不可以使用。
  3. 无缓冲通道,即数据必须即刻送达,其中一方未准备好,即阻塞另外一方。
  4. 缓冲通道,即数据无需便可送达,仅当超过必定阈值时,阻塞其中一方。
// 无缓冲通道
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
*/
  • chan - 用法
  1. chan 结构的设计很是类似于node的异步设计。
  2. 可经过内置的异步方式,实现诸多的设计。
// 迭代型 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)
}
相关文章
相关标签/搜索