首页 > 其他分享 >Go

Go

时间:2022-12-24 14:11:59浏览次数:58  
标签:name v1 fmt Println func Go main

Chapter 01

  • 编译器是全文翻译,解释器是实时翻译。

1.环境搭建

1.1 MAC&Linux

  1. 下载编译器:

    • MAC:在golang.google.cn中点击Download Go,选择Apple macOS即可,默认安装路径是:/usr/local/go/。

    • Linux:

  2. 个人配置

    1. 创建一个任意目录用于存放你写的代码,在目录下创建三个文件夹“bin”、“pkg”、“src”。

    2. bin存放编译后的可执行文件、pkg存放包文件、src存放你的项目。

  3. 配置环境变量

    vim-/.bash_profile//进入后将环境变量写入即可
    //环境变量
    1. go编译器路径:export PATH=/usr/local/go/bin;$PATH
    2. go安装路径:export GOROOT=/usr/local/go
    3. 自己创建的路径:export GOPATH=/users/golangProjects
    4. 自己创建路径下的bin目录:export GOBIN=/users/golangProjects/bin
    1. 查看版本

      • go,进入go

      • go version,显示go的版本

  4. 测试

    cd $GOPATH //快速进入主文件夹
    cd src/
    ls //查看当前文件夹
    mkdir crm //创建project
    touch app.go //创建.go文件
    pwd//查看当前路线
    vim app.go//打开app.go文件
    """
    package main
    import "fmt"
    func main(){//创建函数
    fmt.Println("holle world!")//调用fmt的println函数
    }
    """
    go run app.go //运行程序
    ​
    编译分为三种:
    1.{
    go build//编译
    ./crm //执行程序文件
    go build -o xx//可编译时修改文件名
    //本质是先执行go build 后保存在一个零时文件夹中,然后执行。
    }
    2.go install、go run   //2&3一样都是先执行go build后,再把文件保存在相应文件中。

1.2 Windows

  1. 下载go编译器去官网下,安装编译器后选好目录并创建(注意那三个文件夹也需要创建)。

  2. 设置环境变量:

    PATH=c:/GO/bin;
    GOROOT=c:/GO
    GOPATH=e:/project/go
    GOBIN=e:/project/go/bin
  3. 开发工具:Goland,IDE(集成开发环境)

2.基础学习

2.1 初识包管理

  1. 一个文件夹可以称为一个包,在文件夹中可以创建多个文件。在同一个包下的每个为文件中必须指定相同包名称。

  2. 包分为程序包和模块包:

    1. 程序包的packagemain,程序是需要主程序运行的,所以main就需要一个主函数,这个函数只能有一个。

      package main//主包名
      func main(){//程序主函数入口
      }
      • 程序包中可以创建子包,子包的name与子包的package name相同。同目录下创建的文件可认为是子文件夹的仓库。

      • 主程序调用同级目录下的文件函数时,可直接写函数名加括号,无需写文件名或路径。

      • 主程序调用子级目录下的文件函数时,需要在import中写入程序名/子包名才可调用函数,package名加函数名加括号。

        package main
        import(
        "luggy/api"
        )
      • 函数名首字母大写称为公共函数,其他文件可以调用。函数首字母小写称为私有函数,只能在自文件中使用。

    2. 模块包中的package是除main之外,都可以使用并且无需写main函数指定程序入口。

2.2 输出和输入

  1. 输入分为自带和模块,自带有两钟print和println。

  2. 模块也是go自带的模块“fmt”,其中有三种输出:print、println、printf。

    package main
    ​
    import"fmt"
    func main(){
       Print("baba")//print不带换行
       Println("baba")//println带换行
       fmt.Print("baba")//print不带换行
       fmt.Println("baba")//println带换行
       //printf是格式化输出,其中占位符有%s字符、%d数字、%f是小数、%.2f是保留两位小数并四舍五入。
       fmt.Printf("I'm your %s","dad")
    }
  3. 输入是计算机与人交互,输入由三种:Scan、Scanln、Scanf,这三种都返回两个值,count,err。

    • Scan是要求输入两个或多个时,必须输入相对应的数据,不然会一直等待,每个值用空格分割。

    • Scanln是不管输入几个,只要回车就结束输入状态。

    • Scanf是格式化输入,按照指定的字符串输入并提取数据,在要提取的数据后面加上空格才可以。

      package main
      ​
      import"fmt"
      ​
      func main(){
      var name,age string
      fmt.Println("aaa")
         //count,err := fmt.Scan(&name,&age)
         //count,err := fmt.Scanln(&name,&age)
         count,err := fmt.Scanf("我是你%s,今年%s"&name,&age)
      fmt.Println(name,count,age)
      }
    • 这三种输入都有一个问题,不能还有空格。因此有一种方式解决。

      package main
      import (
      "bufio"
         "os"
      "fmt"
      )
      func main(){
         /*
        os.Stdin是正则输入,可以将输入的存储起来。
        bufio.NewReader()是将输入的转为reader对象。
        reader.ReadLine()是读取并返回三个参数。
        isprefix=false是一次性读完
       isprefix=True是未读完
         */
         reader:= bufio.NewReader(os.Stdin)
         Line,isprefix,err := reader.ReadLine()
         data:=string(Line)
         fmt.Println(isprefix,data,err)
      }
  4. 注释:单行注释用//,而多行注释用/**/

  5. 字符串格式化

    package main
    import "fmt"
    func main(){
       var a,b string
       fmt.Scan(&a,&b)
       fmt.Printf("我是你%s,永远都是你的%s",a,b)    
    }

2.3 初识数据类型

  1. 整型(int)

    • 整型是由10个基数组成的,可以进行运算。

  2. 字符串(string)

    • 双引号引起来的字符、数字、符号都称为字符串,字符串之间可以相加。

  3. 布尔型(bool)

    • 布尔型有两个状态truefalse,计算机中只有真和假。

2.4 变量和常量

  1. 变量是由字母、数字、下划线组成,不能以数字开头,不能使用关键字。

    //变量分为定义和赋值,定义时不赋初值默认是int型默认值是0、string默认值是“”、bool默认值是false
    var age int//定义未赋初值,默认是0
    var name string = "123"//定义并赋值
    age = 12//赋值
  2. 起名时建议使用:见名知意、驼峰式。

  3. 变量简写

    var name="alex"
    name := "alex"
    var name,age,data string
    var(//这种称为因式分解
    name="alex"
       age="18"
       num int
    )
  4. 常量是保持不变的量,在局部和全局都可以使用,通过const定义并赋值。

    package main
    main(){
       const data = 999
       const(
      pi=123
           gender="boy"
      )
    }

2.5 作用域和赋值及内存

  1. 作用域程序层次化,以大括号区分、上级不能使用子级变量,上级可以使用同级变量,下级可以使用上级变量。

  2. 全局变量是在入口外,不可以使用:=定义变量。

  3. a="1234",b=a时b会复制a,而并不会指向同一个内存地址,在变量前加上&可以查看内存地址,当赋值时内存位置不变,但只会变。

  4. 注意:使用int、string、bool这三种数据类型时,如果遇到变量的赋值则会拷贝一份(赋值型)。

2.6 iota

  1. iota可以在因式分解中使用,用来给多个常量或者变量赋连续的值,iota的作用是在需要定义连续值的时候使用。

    package main
    ​
    main(){
       //会自动给后面的变量赋值,值是连续的
       const(
           v1 = iota   //0
           v2//1
           v3//2
    )
       
    }

2.7 编码

  1. ascii以8位表示,最高位用于表示正负。

  2. Unicode分为ucs2(16位表示)和ucs4(32位表示)。

  3. utf-8是Unicode的压缩,以码位范围选择模板。

3.语句和运算符

3.1条件结构

  1. if语句可以用于单分支、双分支和多分枝。

    package main
    import "fmt"
    func main(){
       var number int
       fmt.Println("请输入数字")
       fmt.Scanln(&number)
       if number >0{
           fmt.Println("你输入的数字是个正数")
      }else if number <0{
           fmt.Println("你输入的数字是个负数")
      }else{
           fmt.Println("你输入的是0")
      }
    }
  2. switch也是多分支,使用表达式的结果,再于条件比较。

    package main
    import "fmt"
    func main(){
       var number int
       fmt.Println("请输入数字")
       fmt.Scanln(&number)
       switch true{
       case number==1:
           fmt.Print("a")
       case number==2:
           fmt.Print("b")
       default://所有条件不满足时触发。
           fmt.Print("c")
      }
    }

3.2 循环

  1. for循环,循环是将一段代码重复执行,for循环默认是true。

    for(){//不加条件会一直循环
       循环体
    }
    ​
    for(表达式1,表达式2,表达式3){//表达式1只有在第一次循环时执行,表达式2时条件,表达式3是每次循环都会执行。
       循环体
    }
  2. continue是结束本次循环执行下次循环,break是结束循环。

3.3 跳跃

  1. goto语句,跳跃是指从一个地方跳到一个地方。

    package main
    import "fmt"
    func main(){
        fmt.Println("a")
        goto A		//A的跳跃点
        fmt.Println("b")
        A:			//A的降落点
        fmt.Println("c") 
    }

3.4 运算符

  1. 算数运算符:*、/、%、+、-、++、--

  2. 关系运算符:==、!=、<、>、<==、>==

  3. 逻辑运算:&&、||、!

  4. 位运算:&(与)、|(或)、^(异或)、<<(左移)、>>(右移)、&^(以前面的位基准,让前后的值比较,如果都是1,则将前面的值是1的改为0.)

  5. 赋值运算符:=、+=、-=、/=、%=、<<=、>>=、&=、^=、|=

  6. 运算符优先级:位运算高于算数运算高于关系运算高于逻辑运算。

 

 

4.数据类型

4.1 整型

  1. go 中的整型分为有符号和无符号,有符号包含负号。

  2. 有符号整型分为int8、int16、int32、int64,计算方式是2的几次方。32位操作系统下是2的32次方,正负各占一半。

  3. 无符号整型相同64位操作系统下2的64次方个,正号全占。

  4. 整型的转换

    package main
    import (
    	"fmt"
        "reflect"
        "strconv"
    )
    func main(){
        //1.整型之间的转换
        var v1 int8 =12
        var v2 int16 =23
        v3 :=int16(v1)+v2	//这样可以将其直接转换
        fmt.Println(v3)
        //2.整型与字符串之间的转换
        result:=strconv.Itoa(16)	//将整型转为字符串
        fmt.Println(result,reflect.TypeOf(result))	//typeof是查看数据类型
        result1,err:=strconv.Atoi("234")	//将字符串转为整型,如果是无法转换的字符err会告诉你的。
        fmt.Println(result1,reflect.TypeOf(result1),err)	//typeof是查看数据类型
    }
  5. 进制之间的转换

    package main
    import(
    	"strconv"
        "fmt"
    )
    func main(){
        //只有十进制是整型形式存在的,其他都是字符形式存在。
        v1:=strconv.FormatInt(int64(64),16)	//十进制转其他进制
        fmt.Println(v1)
        //第一个参数是数据,第二个参数是数据的进制,第三个参数是要转成的进制
        result,err:=strconv.ParseInt("123D",16,0)
        fmt.Println(result,err)
        
    }
  6. 常见的数学运算

    package main
    import"math"
    func main(){
        math.Abs(v1)	//取绝对值
        math.Floor(v1)//取最小整数
        math.Ceil(v1)	//取最大整数
        math.Round(v1)//四舍五入
        math.Mod(v1,v2)	//取余数
        math.Pow(v1,v2)	//计算次方
        math.Pow10(v2)	//计算10的几次方	
        math.Max(v1,v2)	//取最大值
        math.Min(v1,v2)	//取最小值
    }
  7. 指针是用来存储内存地址的,主要用于节省内存空间;有两钟定义方式

    • var 变量 * int; //这种创建后默认值是“nil”,它们所存储的内存地址相同

    • 变量:=new(int) //这种创建后默认值是“0”,它们会创建后并指向那块内存地址。

    • nil代表的是空,new用于创建内存并进行内部数据的初始化,而且返回一个指针类型。

2 超大整型

  1. 使用超大整型需要导入“math/big”模块,用big.int来定义。

    import "math/big"
    
    func main(){
        var v1 := new(big.Int)	//也可以创建指针形式的超大整型 
        var v2 big.Int	//定义超大整型
        v2.SetInt64(12)		//通过int64来赋值,最大不能超过2的64次方。
        v2.SetSrting("2222",10)		//通过字符串的形式来赋值的,并不受大小限制。第一个参数是数据,第二个参数是进制。
        v3:=big.NewInt(21)	//newint可以完成定义并赋值。
    }
  2. 超大整型的基本加减乘除

    v1 := big.NewInt(11)
    v2 := big.NewInt(21)
    result := new(big.Int)
    
    //加
    result.Add(v1,v2)
    //减
    result.Sub(v1,v2)
    //乘
    result.Mul(v1,v2)
    //除
    result.Div(v1,v2)
    //除,得商和余
    miner := new(big.Int)	//存余
    result.DivMod(v1,v2,mider)	//存商
    
    var r1 big.Int
    r1.Add(&v1,&v2)		//如果需要将其转换为指针类型,也可以使用变量前面加&的方式来实现。 

4.2 浮点数

1.go自带

  1. 浮点数,在go中分为Float32(4个字节)和Float64(8个字节)。

    package main
    import"fmt"
    func main(){
        var v1 float32	//定义浮点型
        var v2 float32
        v1=0.1
        v2=0.2
        fmt.Println(v1+v2)
    }
  2. float底层存储原理

    1. 先将浮点型数据转换位二进制,整数/2,小数*2。

    2. 科学计数法表示,就是首位为1,剩下的均为小数,用2的n次方来实现。

    3. 存储:以float32为例存储浮点型数据,32位会分为sign、exponent、fraction

      • sign,占最高位的1位字节来表示正负、0表示正数、1表示负数。

      • exponent,除最高一位占8位,共有256种但是正负(-127~128)。存储2的几次方数

      • fraction,存储所有小数数据。

      • float64:sign=1\exponent=11\fraction=52

2.第三方库

  1. decimal需要在本地的Go环境中先安装再使用。第三方包源码地址:https://github.com/shopspring/decimal

  2. 安装第三方包

    go get github.com/shopspring/decimal

    命令执行完成,在$GOPATH/src的目录下就会出现github/shopspring/decimal的目录,这就是第三方模块安排的位置。

  3. 使用decimal包

    package main
    import(
    	"fmt"
        "github.com/shopspring/decimal"
    )
    func main(){
        var v1 = decimal.NewFromFloat(0.000002)
        var v1 = decimal.NewFromFloat(0.00422)
        //加
        var v3 = v1.Add(v2)
        //减
        var v3 = v1.Sub(v2)
        //乘
        var v3 = v1.Mul(v2)
        //除
        var v3 = v1.Div(v2)
        fmt.Println(v3,v4,v5,v6)
        
        var price = decimal.NewFromFloat(2.345)
        var data1 = price.Round(1)	//四舍五入,保留一位小数
        var data2 = price.Truncate(1)//保留一位小数
        fmt.Println(data1,data2)
        
        
    }

4.3 布尔类型

  1. 表示真假,一般是和条件等配合使用,用于满足某个条件时,执行每个操作。

    package main
    
    import(
    	"fmt"
        "strconv"
    )
    func main(){
        //字符串转布尔值
        //true:"1","t","T","true","TRUE","True"
        //false:"0","f","F","false","FALSE","False"
        v1,err := strconv.ParseBool("t")
        fmt.Println(v1,err)
        
        //布尔值转字符串
        v2 := strconv.FormatBool(false)
        fmt.Println(v2)
    }

4.4 字符串

  1. 在编写程序时,使用字符串来进行文本处理的。

    var name string = "李永强"
    fmt.Println(name[0])	//这种索引得到的是一个字节
    fmt.Println(len(name))	//这样可以查看里面有几个字节
    //字符串转为一个字节集合
    byteSet := []byte(name)	//转为字节集合
    fmt.Println(byteSet)	//有九个字节
    //字节集合转为一个字符串
    byteList := []byte{230,173,166,230,178,155,233,189,144}
    targetString := string(byteList)
    fmt.Println(targetString)
    //rune 将字符串转为Unicode字符集码点的集合
    tempSet := []rune(name)
    fmt.Println(tempSet)
    
    //rune转换为字符串
    runeList := []rune{27494,27803,40784}
    targetName := string(runeList)
    fmt.Println(targetName)
    
    //长度处理
    runeLength := utf8.RuneCountInString(name)
    fmt.Println(runeLength)	//处理后长度就变成了3

1.常用功能

  1. 获取长度

    package main
    
    import (
    	"fmt"
        "unicode/utf8"
    )
    func main(){
        var name string = "李永强"
        fmt.Println(len(name))	//获取字节长度
        fmt.Println(utf8.RuneCountInString(name))	//获取字符长度
    }
  2. 是否以什么开头和结尾

    package main
    import(
        "fmt"
        "strings"
    )
    
    func main(){
        name:="李永强"
        result := strings.HasPrefix(name,"李")	//是否以什么字符串开头
        fmt.Println(result)	//输出逻辑值
        result2 := strings.HasSuffix(name,"强")	//是否以什么字符串结尾
        fmt.Println(result1)
    }
  3. 是否包含

    package main
    
    import(
    	"fmt"
        "strings"
    )
    func main(){
        name := "我是你爸爸你相信吗"
        result:=strings.Contains(name,"爸爸")	//判断爸爸是否在里面
        fmt.Println(result)
    }
  4. 变大写和小写

    package main
    import (
    	"fmt"
        "strings"
    )
    func main(){
        name := "liyongqiang"
        result := strings.ToUpper(name)
        result1 := strings.ToLower(name)
        fmt.Println(result,result1)
        
    }
  5. 去两边

    package main
    import(
    	"fmt"
        "strings"
    )
    
    func main(){
        name:="liyongqiang"
        result1 := strings.TrimRight(name,"qiang")
        result2 := strings.TrimLeft(name,"li")
        result3 := strings.Trim(name,"l")
    }
  6. 替换

    package main
    import(
    	"fmt"
        "strings"
    )
    func main(){
        name:="leyongqiang"
        //第一个参数是数据,第二个参数是要替换的,第三个是替换成的,第四个是替换几个(-1代表全部)
        result1 := strings.Replace(name,"e","i",1)
        result2 := strings.Replace(name,"e","i",-1)
    }
  7. 分割

    package main
    import(
    	"fmt"
        "strings"
    )
    func main(){
        name:="aaaaaaavaaaaaa"
        result:=strings.Split(name,"v")
        fmt.Println(result)
    }
  8. 拼接

    package main
    
    import(
    	"bytes"
        "fmt"
        "strings"
    )
    
    func main(){
        //不建议
        message := "aa"+"bb"
        fmt.Print(message)
        
        //建议
        dataList:= []string{"aa","bb"}
        result := strings.Join(dataList,"_")
        fmt.Println(result)
        
        //建议(1.10之前)
        var buffer bytes.Buffer
        buffer.WriteString("aa")
        buffer.WriteString("bb")
        data := buffer.String()
        fmt.Println(data)
        
        //建议(1.10之后)
        var builder strings.Builder
        builder.WriteSering("aa")
        builder.WriteSering("bb")
        value := builder.String()
        fmt.Println(value)
    }
  9. string和int互转

    package main
    
    import (
    	"fmt"
        "strconv"
    )
    func main(){
        num := "666"
        var result = strconv.Itoa(888)	//转为string
        fmt.Println(result)
        //内部调用的就是ParseInt
        var data,_ = strconv.Atoi(num)	//转为int
        fmt.Println(data)
       
    }
  10. 字符串与字节集合和rune集合

    package main
    import (
        "fmt"
        "strconv"
       	"unicode/utf8"
    )
    func main(){
        var name string ="李永强"
        //字符串转字节集合
        byteSet := []byte(name)
        fmt.Println(byteSet)
        //字节集合转字符串
        byteList := []byte{230,173,166,230,178,155,233,189,144})
        targetString := string(byteList)
        fmt.Println(targetString)
        //rune 将字符串转为Unicode字符集码点的集合
        tempSet := []rune(name)
        fmt.Println(tempSet)
    
        //rune转换为字符串
        runeList := []rune{27494,27803,40784}
        targetName := string(runeList)
        fmt.Println(targetName)
        
    }
  11. string和字符

    package main
    
    import(
    	"fmt"
        "unicode/utf8"
    )
    func main(){
        //数字转字符串
        v1 := string(65)
        fmt.Println(v1)
        //字符串转数字
        v2,size := utf8.DecodeRuneInString("A")
        fmt.Println(v2,size)
        
    }

2.索引切片

  • 只能操作字符串,其他类型不可以的

    package main
    import "fmt"
    func main(){
        var name string = "李永强"
        //1.索引获取字节
        v1 := name[0]
        fmt.Println(v1)
        //2.切片获取字节区间
        v2 := name[0:3]
        fmt.Println(v2)
        //3.手动循环获取所有字节
        for i:=0;i<len(anme); i++{
            fmt.Println(i,name[i])
        }
        //4.for range循环获取所有字节
        for index,item := range name{
            fmt.Println(index,item)
        }
        //5.转成rune集合
        dataList := []rune(name)
        fmt.Println(dataList[0],string(dataList[0]))
    }

4.5 数组

  1. 数组是由定长且元素类型一致的数据集合。

    //方式一:先声明再赋值(声明时内存中已开辟空间,内存初始化的值是0)
    var number [3]int
    number[1] =34
    //方式二:声明并赋值
    var names = [2] string{"李永强","吴佩琦"}
    //方式三:声明并赋值加指定位置
    var ages = [3]int{0:23,1:34,2:12}
    //方式四:省略个数
    var name = []string{"吴佩琦","李永强"}
    //声明指针型的数组,不会开辟内存初始值数组的值是nil
    var number*[3]int
    //声明数组并初始化,返回的是指针类型数组
    number := new([2]int)
  2. 数组不仅有一维数组还有,二维和多维

    package main
    func main(){
        name :=[][2]string{"aa","bb","cc"}
        name :=[2][2]string{"aa","bb","cc"}  
    }
  3. 数组的内存地址是连续的,数组的内存地址实际上就是第一个元素的内存地址,每个字符串的内部存储:len+str。

    type stringStruct struct {
        str unsafe.Pointer
        len int
    }
  4. 可变和拷贝

    1. 可变,是指数组的大小不变而值可变。

    2. 将一个变量赋予另一个变量时会复制一份的

  5. 索引切片循环

    package main
    import "fmt"
    func main(){
        //1.长度
        name := [2]string{"aa","bb"}
        fmt.Println(len(name))
        //2.切片
        name := [2]string{"aa","bb","cc"}
        v2 := name[0:1]
        fmt.Println(v2)
        //3.循环
        name := [2]string{"aa","bb","cc"}
        for i:=0;i<len(name); i++{
            fmt.Println(i,name[i])
        }
        //4.for range循环
        name := [2]string{"aa","bb","cc"}
        for index,item := range name{
            fmt.Println(index,item)
        }
    }

4.6 切片

  1. 切片也被称为动态数组,切片是Go中重要的数据类型,每个切片对象内部都维护着:数组指针、切片长度、切片容量三个数据。

  2. 在向切片中追加的数据个数大于容量时,内部会自动扩容且每次扩容都是当前容量的2倍(当容量超过1024时每次扩容则指增加4分之一的容量)。

  3. 创建切片

    //创建切片
    var nums []int
    
    var data = []int{11,22,33}
    //make只用于 切片、字典、channel
    //第二个参数是初始化个数,第三个参数是声明个数
    var users = make([]int,1,3)
    //创建切片(指针型)
    var v1 =new([]int)	//只声明并不初始化
    
    var v2*[]int	//声明后,初始化指向nil
  4. 自动扩容

    package main
    import "fmt"
    func main(){
        v1 := make([]int,1,2)
        fmt.Println(len(v1),cap(v1))
        v2 := append(v1,66)			
        //v1和v2地址相同但是,因取值范围的限制v1只能取到【0】的值,v2可以取到【0:1】的值。
        v3 := append(v2,77)
        //当扩容时,地址会发生变化,v2和v3的地址就不同,给v3修改时,v2中的值并不变化。
        
        
    }

1.常用功能

  1. 长度和容量

    v1 :=[]int{11,22,33}
    fmt.Println(len(v1),cap(v1))
  2. 索引和切片

    v1 :=[]int{11,22,33}
    v1[0]//注意虽然定义了,但是没有初始化或赋值的,也不可以索引
    v1[1]
    v1[2]
    v2 :=v1[0:1]
    v3 :=v1[:2]
    v4 :=v1[1:]
  3. 追加和删除

    package main
    import "fmt"
    func main(){
        v1 :=[]int{11,22,33,44,55,66}
        v2 :=append(v1,77)
        v3 :=append(v1,88,99)
        //使用另一个切片时,需要在后面加上三个点才可以使用
        v4 :=append(v1,[]int{100,200,300}...)
        //go本身并没有删除,我们可以使用修改来实现
        //它们本身还是同一个地址,使用v1输出时就会发现,最后一个值出现了两边。
        deleteNum :=2
        v5 :=append(v4[:deleteNum],v4[deleteNum+1:]...)
        
    }
  4. 循环

    package main
    import "fmt"
    
    func main(){
        v1 :=[]int{11,22,33,44,55,66}
        for i := 0;i<len(v1);i++{
            fmt.Println(i,v1[i])
        }
        for index,value := range v1{
            fmt.Println(index,value)
        }
    }

4.7 字典类型(Map)

  1. map是以“键:值”形式存储的数据类型,这种存储方式最大的有点就是查询速度快,由应为他底层是基于哈希表存储的。

  2. 取模+拉链法大概了解一下。

    1. 写好键值对后将键转为哈希值,再将哈希值 mod 4 后将结果按顺序存储(重复时并形存储)。

  3. Map的特点是键不可以重复、键必须是可哈希的(int/bool/float/string/array)、Map是无序的。

1.声明和初始化

  1. Map的键值对增加、修改使用的都是“变量[键]=值”,map不管扩不扩容,它们的内存地址永远相同。

    //声明,声明时记得把大括号带上
    UserInfo := map[string]string{}
    
    //声明并初始化
    UserInfo := map[string]string{"name":"李永强","age":"18"}
    
    //查看
    fmt.Println(UserInfo["name"])
    for key,value := range data{
        fmt.Println(key,value)
    }
    
    //当map中没有此键值对时是增加,有时是修改
    UserInfo["age"]=19
    UserInfo["gender"]="男"
    //删除,参数一是map,参数二是键
    delete(UserInfo,"gender")
    
    //使用make,make定义时可以不加大括号
    data :=make(map[string]int)
    data["a1"]=1
    data["a2"]=2
    
    //new,不能直接使用只能用于map转存,定义不使用new也不加大括号的用法相同。
    value := new(map[string]int)
    value = &UserInfo
    
    //数组做键值对
    v1 := make(map[2]int)int)
    v1[[2]int{1,2}]=2
    v1[[2]int{1,4}]=2
    
    ...  //代表任意类型
    //map嵌套就那么个,简单的很

2.原理解析

  1. map创建后,每个键值对会有count计数并创建桶(2**B),每个桶中可存放8个(tophash哈希值、keys、values、overflow指针)。

  2. 初始化

    1. 创建一个hmap结构体对象,生成一个哈希因子hash0并赋值到hmap对象中(用于后续为key创建哈希值)。

    2. 根据hint=10,并根据算法规则来创建B,根据B去创建桶(bmap对象)并存放在buckets数组中。

      • 当B小于4时,2^B(标准桶)

      • 当B大于4时,2^B+2^(B-4)(标准桶+溢出桶)

      • 注意:每个bmap中可以存储8个键值对,当不够存储时需要使用溢出桶,并将当前bmap中的overflow字节指向溢出桶的位置。

4.8 指针

  1. 指针相当于创建了一个地址的引用,以后根据这个引用再去获取他里面的值。

  2. 取指针的指针时,需要设置好相应的*才可以。

    name := "wupeiqi"
    var a1 *string = &name
    var a2 **string = &a1
    var a3 ***string = &a2
    //一定要把*号写够,*号代表指针的引用层数,如果只写了一个*就代表直接储存name的内存地址,而写够后a3储存a2的内存地址。
  3. 计算指针

    package main
    
    import (
    	"fmt"
        "unsafe"
    )
    func main(){
        dataList := [3]int8{11,22,33}
        //1.获取数组第一个元素的地址(指针)
        var firstDataPtr *int8 = &dataList[0]
        //2.转换成Pointer类型
        ptr := unsafe.Pointer(firstDataPtr)
        //3.转换成uintptr类型,然后进行内存地址的计算
        targetAddress :=uintptr(ptr)+1
        //4.根据新地址,重新转成Pointer类型
        newPtr := unsafe.Pointer(targetAddress)
        //5.Pointer对象转换为int8指针类型
        value :=(*int8)(newPtr)
        //6.根据指针获取值
        fmt.Println("最终结果为",*value)
    }

4.9 结构体

  1. 结构体时一个复合类型,用于表示一组数据,结构体有一系列属性组成,每个属性都有自己的里类型和值。

  2. 定义

    type 结构体名称1 struct {
        字段 类型 标签	//标签可加可不加,主要用于提示。
    }
    
    type 结构体名称2 struct {
        字段 类型 标签
        字段 结构体名称1	//这种是结构体嵌套
        结构体名称1		//这种也是结构体嵌套,但是结构体名称1也是结构体名称2中的字段。也称匿名字段
    }
  3. 初始化

    //可以按位置用逗号分割,给赋予不同类型的数据。
    var 结构体对象 = 结构体名称2{"数据",17}
    结构体对象.字段	//这样可以获取对应的值。
    
    //定义一个结构体
    type ageN struct {
        age int
    }
    type genderS struct {
        gender string
    }
    type Person struct {
        name string
        hobby []string
        agen ageN
        genderS
    }
    //方式一:先后顺序
    var p1 = Person{"liyongqiang",[]string{"computer"},ageN{12},genderS{"男"}}
    fmt.Println(p1.name,p1.hobby,p1.agen.age,p1.gender)
    
    //方式二:关键字
    var p2 = Person{name:"liyongqiang",hobby:[]string{"computer"},agen:ageN{age:12},genderS:genderS{gender:"男"}}
    fmt.Println(p2.name,p2.hobby,p2.agen.age,p2.gender,p2.genderS.gender)
    
    //方式三:先声明再赋值
    var p3 Person
    p3.name = "liyongqiang"
    p3.hobby = []string{"computer"}
    p3.agen = ageN{age:12}
    p3.genderS = genderS{gender:"男"}
    p3.gender = "男"
  4. 结构体指针

    type  Person struct {
        name string
    }
    //初始化结构体指针
    p1 := &Person{"liyongqiang"}
    
    p2 := *Person = new(Person)
    p2.name = "liyongqiang"
  5. 标签的查询方式

    package main
    import (
    	"fmt"
        "reflect"
    )
    func main(){
        type Person struct{
            name string "姓名"
            age int32 "年龄"
        }
        p1 := Person{name:"wupeiqi",age:18}
        p1Tyep := reflect.TypeOf(p1)
        //top1
        filed1 := p1Type.Field(0)
        fmt.Println(filed1.Tag)
        //top2
        filed2,_:= p1Type.FieldByName("name")
        fmt.Println(filed2.Tag)
        //循环获取
        fieldNum :=p1Type.NumField()
        for index := 0;index<fieldNum;index++{
            field:=p1Type.Field(index)
            fmt.Pringln(field.Name,field.Tag)
        }
        
    }

4.10 函数

  1. 函数的基本写法

    func 函数名(参数名 参数类型)返回值类型{
        代码块
        return 返回值
    }
    变量 :=函数名(参数值)
  2. 函数做参数

    package main
    
    import "fmt"
    
    func add100(arg int)(int,bool){
        return arg + 100,true
    }
    //这种也可以称为起别名。 
    type f1 func(arg int)(int,bool)
    func proxy(data int,exec func(int) (int,bool)或f1) int{
        data,flag := exec(data)
        if flag {
            return data
        }else{
            return 9999
        }
    }
    func main(){
        fesult := proxy(123,add100)
        fmt.Println(result)
    }
  3. 接收多个参数

    package main
    
    import "fmt"
    //可接受多个int类型的参数,
    func do(num...int) int{
        fmt.Println(num)
        return sum
    }
    func main(){
        r1:=do(1,4,5,6)
        fmt.Println(result)
    }
  4. 函数做返回值

    package main
    
    import "fmt"
    
    func add100(arg int)(int,bool){
        return arg + 100,true
    }
    
    type f1 func(arg int)(int,bool)
    
    func proxy(data int)  func(int) (int,bool)或f1{
        pass
        return add100
    }
    func main(){
        fesult := proxy(123,add100)
        result := fesult(145)
        fmt.Println(result)
    }
  5. 匿名函数

    package main
    import "fmt"
    func F1 () func(int) string{
        return func()string{
            return "baba"
        }
    }
    func main(){
        v1 := func() int {
            return 123
        }
        //自执行
        value := func() int {
            return 123
        }()
    }
  6. 闭包

    package main
    
    import "fmt"
    
    func main(){
        var functionList []func()
        
        for i := 0;i<5;i++{
            function := func(arg int)func(){
                return func(){
                    fmt.Println(arg)
                }
            }(i)
            functionList = append(functionList,function)
        }
        functionList[0]()
        functionList[1]()
        functionList[2]()
    }
  7. defer

    package main
    import "fmt"
    
    func do() int{
        fmt.Print(1)
        //defer的效果是延迟执行,函数执行完之后执行。
        defer fmt.Print(2)
        defer fmt.Print(3)
        fmt.Print(4)
        return 666
    }
    func main(){
        ret:=do()
        fmt.Println(ret)
    }

    Type自定义类型,就那么个用法,自己用就行

  8.  

标签:name,v1,fmt,Println,func,Go,main
From: https://www.cnblogs.com/fxy1024/p/17002825.html

相关文章

  • 1005.Django自定义过滤器及标签
    一、关于自定义自定义的引入内置函数--------->自定义函数内置模块--------->自定义模板内置过滤器------>自定义过滤器内置标签--------->自定义标签二、文件路径配......
  • 在Dubbo-go中使用TLS加密进行安全通信
    1背景Dubbo-go在Getty/Triple/Grpc三个通信层面支持TLS链路安全通信。2原理2.1证书机制:ps:可以先提前了解非对称加密机制。CA(CertificationAuthority)负责生成根证书......
  • Django
    第1章1.自己开发web框架web种类:第一种,帮你把下面所有的事都做了。Tornado:做了所有的事。第二种,不办你做socket的事,再的都帮你做了。wsgiref:做socket服务......
  • 1004.Django模板标签
    一、常用标签模板标签标签在渲染的过程中提供任意的逻辑。这个定义是刻意模糊的。例如,一个标签可以输出内容,作为控制结构,例如“if”语句或“for”循环从数据库中提取内......
  • 框架第十一课---django中间件三个了解的方法,基于django中间件实现功能的插拔式设计,coo
    昨日内容回顾forms组件渲染标签form_obj=MyForm()方式1:form_obj.as_p\form_obj.as_ul\form_obj.as_table方式2:form_obj.username.labelform_obj.username方......
  • django_ORM基础字段和选项
     一、修改ORM1、任何关于表结构的修改,务必在对应模型类上修改。2、在上一篇博文中,创建了bookstore_book表,如果需要再添加一个名为info(varchar100)的字段,则需要如下操......
  • typora+picgo+阿里云oss
    下载地址:https://wwlc.lanzouy.com/b01k9nnli密码:9kdn安装picgo:按照提示安装即可。配置阿里云oss上面的四项配置参考下图附阿里云oss开通,几块钱几年,便宜得很......
  • Kagol:2022年最值得推荐的前端开源文章
    大家好,我是Kagol,VueDevUI作者,从2020年开始一直专注于前端开源组件库的建设,在前端开源组件库、开源社区运营方面积累了一些经验,2020年主要的创作也是围绕前端组件库和开......
  • 9) TestProgressLeader(raft_test.go:0-350)
    【TestProgressLeader】测试leader的progress.match1)写5条消息2)生成ready(模拟本地盘写)3)advance(ready)  leader的match变为6,next=7 【TestProgressResumeByHear......
  • MongoDB 索引原理与索引优化
    转载请注明出处:1.MongoDB索引索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种......