zoukankan      html  css  js  c++  java
  • GO入门学习

    Go语言环境配置(Linux下)

    下载GO源代码

    Google官方网站:https://golang.org/dl/

    Go官方镜像:https://golang.google.cn/dl/

    中文网站:https://studygolang.com/dl

    安装GO源代码

    tar -zxvf go.... -C /usr/local/

    修改环境变量

    vim ~/.bashrc

    export GOROOT=/usr/local/go
    export GOPATH=$HOME/go
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
    GOROOT表示源代码位置
    GOPATH表示开发者GO的项目默认路径
    

    source ~/.bashrc

    go version检查是否安装成功

    go --help检查是否安装成功

    GO IDE

    • Goland
    • VScode
    • Vim + Go 插件

    Golang 概览

    优势

    极简单的部署方式

    • 可直接编译机器码(编译速度可以超过C)
    • 不依赖其它库ldd 查看依赖
    • 直接运行即可部署(运行速度慢于C/C++)

    静态类型语言

    • 编译时检查出来隐藏的大多数问题

    语言层面的并发

    • 天生的并发支持
    • 充分利用多核(切换成本低 充分利用CPU)
    package  main
    import (
    	"fmt"
        "time"
    )
    
    func goFunc(i int) {
        fmt.Printf("goroutine", i , "...")
    }
    
    func main() {
        for i:= 0; i < 10000; i++ {
            go goFunc(i) // 开启协程
        }
        time.Sleep(time.Second)
    }
    

    强大的标准库支撑

    • runtime系统调度机制
    • 高效的GC垃圾回收
    • 丰富的标准库
      • 加密解密
      • 底层库
      • email
      • 文本
      • 输入输出
      • 数学
      • 压缩
      • 测试
      • 文件系统
      • 进程、线程Goroutine
      • 数据持久化与交换
      • 网络通信
      • 同步机制
      • 应用构建
      • 数据结构与算法

    简单易学

    • 25个关键字
    • C语言简洁基因,内嵌C语法支持
    • 面向对象特征(继承、多态、封装)
    • 跨平台

    大厂常用

    • Google
    • facebook(facebookgo)
    • Tencent(蓝鲸)
    • Baidu(BFE, 通讯消息, 百度云盘Go版本)
    • 京东
    • 小米、七牛(原生GO公司)、阿里巴巴、bilibili、ByteDance

    image-20210314202722239

    image-20210314202810994

    使用领域

    云计算基础设计领域

    • Docker
    • K8s
    • etcd
    • consul
    • cloudflare CDN
    • 七牛云存储

    基础后端软件

    • tidb
    • infuxdb
    • cockroachdb

    微服务

    • go-kit
    • micro
    • monzo bank的typhon
    • bilibili
    • tarsgo

    互联网基础设施

    • 以太坊
    • hyperledger

    缺点(不足)

    包管理

    大部分包都在Github上

    无泛化类型

    所有Exception都用Error来处理

    没有try catch

    对C的降级处理,并非无缝,没有C降级到ASM那么完美(序列化问题)

    兼容C代码也只是通过Cgo来调用C的代码

    Go基础

    从main方法来了解go的语法规则

    image-20210314204009126

    image-20210314204105046

    package main // 当前程序属于main包
    /*
    import "fmt"
    import "time"
    */
    
    import (
    	"fmt"
        "time"
    )
    
    // main 函数
    
    func main() { // 花括号只能是这种代码风格
        fmt.Printf("Hello GO")
        time.Sleep(1 * time.Second)
    }
    
    

    编译并执行:

    go run hello.go

    四种变量声明方式

    // 声明全局变量 1 2 3 方法可以
    var gA int = 100
    var gB = 200
    
    // 第四种方法声明全局变量 只能在函数体内部声明
    //gC := 200
    
    func Var() {
    	// 四种变量声明方法
    
    	// 1. 声明一个变量 默认值是0
    	var a int
    	fmt.Println(a)
    
    	// 2. 声明变量初始化
    	var b int = 100
    	fmt.Println(b)
    
    	// 3. 在初始化的时候,让编译器根据值来匹配类型
    	var c = 100
    	fmt.Printf("type of C = %T
    ", c)
    
    	// 4. 常用的方法 省去var关键字 直接自动匹配
    	e := 100
    	fmt.Printf("type of e = %T
    ", e)
    
    	// 声明多个变量
    	var x, y int = 100, 200
    	var xx, yy = 100, "xx"
    
    	var (
    		vv int  = 100
    		jj bool = true
    		ss      = "aaaa"
    	)
    	var emptyString string
    	fmt.Println(emptyString, x, y, xx, yy, vv, jj, ss)
    }
    

    常量与iota

    package main
    
    import (
    	"fmt"
    )
    
    // const 定义枚举属性
    const (
    
    	// 可以在const添加关键字 iota, 每一行的iota都会累加1, 第一行默认是0
    	BEIJING = 10 * iota
    	SHANGHAI 
    	SHENZHEN 
    )
    const (
    	a, b = iota + 1, iota + 2 // iota = 0
    	c, d // iota = 1
    	e, f
    
    	g, h = iota * 2, iota * 3
    	
    )
    
    // 枚举属性
    
    func main() {
    	// 常量 只读
    	const length int = 10;
    
    }
    

    函数多返回值

    func fool(a string, b string) int {
        return 100
    }
    //匿名返回多个值
    func fool2 (a string, b string) (int, int) {
        return 100 ,2
    }]
    // 返回多个值带有形参名称 默认地址为0
    func fool3(a string, b int) (r1 int, r2 int) {
        r1 = 1000;
        r2 = 2000;
        return 
    }
    func fool4 ()(r1, r2 int) {
        r1 = 1
        r2 = 2
        return  
    }
    
    func mian() {
        c := fool ("aa", "bb")
        a , b = fool2("aa", "bb")
        ret1, ret2 = fool3("aa", 12)
        
    }
    

    Import导包路径与init方法调用

    image-20210314213650071

    import(
    	"GolangStudy/5-inti/lib1" // 相对路径完成
    )
    

    image-20210314214136705

    import匿名及别名导包

    import (
    	_ "GolangStudy..." // _为匿名 可能不使用
        myLib "Lib" // 别名
        . "MyLib" // MuLib包下的方法都是在本包下的
    )
    func main() {
        muLib.test()
        MyLibTest()
    }
    

    GO指针

    package main
    import "fmt"
    func changeValue(p *int) {
        *p = 10
    }
    func main() {
        var a int = 1
        changeValue(&a)
        fmt.Println("a = ", a)
    }
    

    defer语句调用顺序

    defer按照压栈的顺序来打印

    func main() {
        defer fmt.Println("main end1")
        defer fmt.Println("main end2")
        defer myFunc()
    }
    

    image-20210315090112717

    数组与动态数组的区别

    func main() {
        var MyArray [10]int // 默认0
        var MyArray2 [10]int{1, 2, 3, 4} // 默认0
        
        for idx, value range MyArray2 {
            
        }
    }
    
    func print(myArray []int) {
        // 引用传递
        for _, value := range myArray {
            
        }
    }
    func main() {
        MyArray := []int {1, 2, 3, 4}// 默认0
        
    }
    

    四种slice切片声明定义方式

    func main() {
        // 声明初始长度为3的
        slice1 := []int{1, 2, 3}
        
        // 声明slice是一个切片 但是没有空间
        var slice2 []int
        slice2 = make([]int, 3) // make来开辟空间
        slice2[0] = 100
        
        //1 ,2 合二为一 
        var slice3 []int = make([]int, 3)
        
        slice4 := make([]int, 3)
        
        
        fmt("%d, %v", len(slice1), slice1) // %v 打印详细信息
        
    }
    

    slice切片追加与截取

    追加

    func main() {
        var numbers = make([]int, 3, 5)
    }
    

    image-20210315124153701

    func main() {
        var numbers = make([]int, 3, 5) // len = 3, cap = 5
        numbers = append(numbers, 1) // 追加1 len = 4, cap = 5
    }
    

    超过之后采用初始化的cap * k进行 append

    func main() {
        var numbers = make([]int, 3) // len = 3 cap = 3
        numbers = append(numbers, 1) // 追加1 len = 4, cap = 6
    }
    

    截取:浅拷贝

    func main() {
        numbers := []int{1, 2, 3}
        s1 := s[0 :2]
    }
    

    深拷贝

    func main() {
        numbers := []int{1, 2, 3}
        s1 := make([]int, 3)
        copy(s1, numbers)
    }
    

    map三种声明方式

    func main() {
        
        // 1.声明myMap为map类型 key是int value 为string
        var myMap map[int]string // 默认空map
        myMap := make(map[int]string, 10) // 开辟十个空间
        myMap[1] = "java" // hash表 所以是乱序
        myMap[222] = "c++"
        
        // 2. 第二种声明
        myMap := make(map[int]string)
        myMap[2] = "java"
        
        
        //3. 第三正声明方式
        myMap := make(map[string]string) {
            "aa" : "java"
            "sss" : "aaaa"
        }
        
    }
    

    map的使用方式

    func main() {
        
        cityMap := make(map[string] string)
        
        // 插入或修改
        cityMap["china"] = "beijing"
        cityMap["Jappen"] = "Tokyo"
        //遍历
        for key, value := range cityMap {
            
        }
        
        // 删除
        delete(citMap, "china")
        
    }
    

    结构体

    // typedef 
    type myint int
    
    // 结构体
    type Book struct {
        title string
        auth string
        id int
        
    }
    
    func printBook(book Book) {
        // 副本传递
        fmt.Printf("%dv
    ", book1)
    }
    func main() {
        var book1 Book
        book1.title = "Golang"
        fmt.Printf("%dv
    ", book1)
        
    }
    

    面向对象与类的封装

    // 类就是结构体来访问方法 类名大写表示对其它包开放 否则内部访问
    type Hero struct {
        Name string
        Ad int
        level int  // 内部访问 private 
    }
    // this拷贝执行当前调用的对象
    func (this Hero) GetName(){
        fmt.Printf("name = %s", this.name)
    }
    // this * 指针可以修改
    func (this *Hero) SetName(name string){
        this.Name = name
    }
    
    func main() {
        hero := Hero{Name : "zhang3", ad:100, level:1}
    }
    

    面向对象继承

    type Human struct {
        name string
        sex string
    }
    func (this *Human) Eat() {
        fmt.("Human Eat.")
    }
    func (this *Human) Walk() {
        fmt.("Human walk.")
    }
    
    type SuperMan struct {
        Human
        level int
    }
    // 覆盖、重写父类方法
    func (this *superMan) Eat() {
        fmt.("Superman Eat.")
    }
    
    
    func main() {
        h := Human{"zhang3", "female"}
        h.Eat()
        h.walk()
        
        s := SuperMan{
            Human{"li4", "femal"}
            levle : 1
        }
        s.Walk() // 父类的方法
        s.Eat() // 子类的方法
        
        var s SuperMan
        s.name = "li4"
        s.sex = "male"
        s.level = 88
        
    }
    
    

    多态的实现及基本要素

    // 本质是一个指针 可以指向实现该接口的任意类
    type Animal interface {
        Sleep()
        GetColor() string
        GetType() string
    }
    
    type Cat struct { 
        color string
    }
    func (this *Cat) Sleep() {
        fmt.Printl("Cat is Sleep")
    }
    func (this *Cat) GetColor() string{
        return this.color
    }
    func (this *Cat) GetType() {
        return "Cat"
    }
    
    type Dog struct { 
        color string
    }
    func (this *Dog) Sleep() {
        fmt.Printl("Cat is Sleep")
    }
    func (this *Dog) GetColor() string{
        return this.color
    }
    func (this *Dog) GetType() {
        return "Cat"
    }
    
    func ShowAnimal(animal AnimalIF) {
        animal.Sleep() // 多态实现
    }
    
    func main() {
        var animal AnimalIF // 接口数据类型 指针
        animal = &Cat{"Green"}
        animal.Sleep() 
    }
    
    

    空接口万能类型与类型断言机制

    func myFunc(arg interface {}) {
        fmt.Printf("myFunc")
        fmt.Println(arg)
        
        // 区分底层数据类型 -- 类型断言
        value,ok = arg.(string) // 判断是否是string
        if !ok {
           // not string
        } else {
           // is string
        }
        
    }
    
    func main() {
        book := Book{"golang"}
        myFunc(book)
        myFunc(123)
    }
    

    内置pair结构

    image-20210315221157027

    image-20210315221622665

    image-20210315221937266

    反射机制reflect包

    ValueOf 返回pair中的value

    TypeOf返回pair中的type

    import(
    	"reflect"
    )
    // 基本用法
    func reflectNum(arg interface{}) {
        fmt.Println("type:", reflect.TypeOf(arg))
        fmt.Println("type:", reflect.ValueOf(arg))
    }
    

    image-20210315222900937

    结构体标签

    package main
    type resume struct {
        // 说明作用 有什么作用
        Name string `info:"anme" doc:"我的名字"`
        Sex string `info:"sex"`
    }
    func findTag(str interface{}) {
        t := reflec.TypeOf(str)
        for i := 0; i < t.NumFiled() {
            tag := t.Filed(i).Tag.Get("info")
            fmt.Printf(tag)
        }
    }
    
    func main() {
        
    }
    

    结构体标签在json中的应用

    import "encoding/json"
    type Movie struct {
        Title string `json:"title"` // 标签映射
        Year int	`json:year`
        Price int	`json:rmb`
        Actors []string `son:actors`
    }
    
    func main() {
        movie := Movie{"喜剧之王", 200, 10, []string{"xingye", "zhangbozhi"}}
        // 编码过程:结构体 -> json
        jsonStr, err := json.Marshal(movie)
        if err != nil {
            return
        }
        fmt.Println(jsonStr);
        
        // 解码过程 jsonStr -> 结构体
        myMovie := Movie{}
        err = json.Unmarshal(jsonStr, &myMovie)
        if err != nil {
           	return 
        }
        
    }
    

    创建goroutine

    // 子goroutine
    func newTask() {
        i := 0
        for {
            i ++
            fmt.Printf("new Goroutine")
            time.Sleep(1 * time.Second)
        }
    }
    
    // 主goroutine
    func main() {
        go newTask
        i := 0
        
        for {
            i++
            fmt.Printf("new Goroutine")
            time.Sleep(1 * time.Second)
        }
    }
    

    匿名函数

    // 子goroutine
    
    
    // 主goroutine
    func main() {
        go func() {
            
        }
    }
    

    image-20210316182744344

    拿不到goroutine的返回值

    Channel

    image-20210316183149650

    无缓冲channel

    image-20210316183602928

    有缓冲的channel

    image-20210316183704473

    当通道被填满(或者为空)的时候就会阻塞掉。

    image-20210316183855913

    channel的关闭特点

    image-20210316184337449

    • 关闭后不能再发送,但是可以继续接收
    • nil channel 无论收发都要被阻塞

    channel与range

    image-20210316184924796

    迭代查询c的range

    channel与select

    image-20210316185059458

    image-20210316185233033

    select 具备监听多路channel的监控状态

    GoModules

    GOPATH工作模式的弊端

    • 没有版本控制概念
    • 无法同步一致第三方版本号
    • 无法指定当前项目引用的第三方版本号

    image-20210320120502215

    image-20210320120720208

    GoModules初始化项目

    • 开启go模式

      go env -w GO111MODULE=on

    • 创建新项目路径:新建任意文件夹

    • go mod 初始化工作

      go mod init github.com/DengSchoo/module_test

    • 下载依赖的包

      go get github.com/

    image-20210320122511560

    image-20210320122540522

    改变项目模块的版本依赖关系

    image-20210320123121562

    项目一《Golang即时通讯系统》

    架构图

    image-20210320123227785

    版本迭代

    • 版本一:构建基础Server
    • 版本二:用户上线功能
    • 版本三:用户消息广播机制
    • 版本四:用户业务层封装
    • 版本五:在线用户查询
    • 版本六:修改用户名
    • 版本七:超时强踢功能
    • 版本八:私聊功能
    • 版本九:客户端实现

    生态拓展及未来成长

    web框架

    beego

    gin

    echo

    Iris

    微服务框架

    go kit

    Istio

    容器编排

    K8s

    swarm

    服务发现&注册

    consul

    存储引擎

    kv存储:etcd

    分布式存储:tidb

    静态建站

    hugo

    中间件

    消息队列:nsq

    Tcp长链接框架(轻量级服务器):zinx

    Leaf(游戏服务器)

    RPC框架 gRPC

    Redis集群:codis

    爬虫框架

    go query

  • 相关阅读:
    nginx
    不再想写博客的大众集合教程
    数据结构与算法之算法
    数据结构与算法
    yii2的安装使用
    git的使用方法总结
    php生成图片验证码
    git推送失败的问题
    配置nginx支持thinkphp框架
    centos下的lnmp环境搭建
  • 原文地址:https://www.cnblogs.com/DengSchoo/p/14585050.html
Copyright © 2011-2022 走看看