相关文章推荐
小胡子的石榴  ·  VS ...·  1 年前    · 
失眠的刺猬  ·  [reportlab ...·  1 年前    · 
留胡子的茶壶  ·  在pyqt5 ...·  1 年前    · 
.\main.go:8:21: constant 1000 overflows uint8

在Python里面定义1个数字类型的变量,无需考虑系统底层内存存储这个变量 需要开销多大 存储空间(位),因为Python解释器自动计算、分配;

在Go里面不行!Go语言的整型分为有符号整型和无符号整型2大类。

计算机只认识0、1,所谓有符号和无符号就是 计算机到底需要分配多大的存储空间(位/字节)来存储这些数字。

有符号整型:计算机 使用第0位表示数字的 +正 -负性质 ,其他位用来表示数字。(可表示负数,但是表示正数的范围小!)

无符号整型:计算机使用全部的位 来表示数字(不可以表示负数,但是可表示正数的范围很大!)

综上所述:

有符号整型 :表示数字的位 比无符号少了1位,所以有符号整型可 表示负数,但是表示正数字范围小。

无符号整型 :没有符号位 无法表示负数,但是表示正数的范围会更大。

所有我们需要根据 数字的大小范围来选择合适的整数的类型

注意即便uint8和uint20同属于整型和无符号整型,也有不同数据类型之分。

有符号整型:

int8、int16、int32、int64

无符号整型:

uint8、uint16、unit32、uint64

不同整型之间的相互转换

在go语言中不同位的整型相互转换时,由低位转成高位,不会有问题,但是由高位转换成低位就会表示错误。

func main() {
  var v1 int8=10
  var v2 int16=19
  //整型数据类型转换
  v3:=int16(v1)+v2
  fmt.Println(v3,reflect.TypeOf(v3))//29 int16
  //低位转向高位,没问题。高位转低位无法转
  var v4 int16 = 2020
  v5:=int8(v4)
  fmt.Println(v5)//注意这里不会报错,而是轮回转换。

整型和字符串之间的转换(strconv)

 使用strconv.Atoi(string)可以把字符转换成整型,trconv.Itoa(int)把数字转换成字符串。

 //2.整型和字符串类型之间的的转换
    var str1 string ="132201988666"
    fmt.Println(strconv.Atoi(str1))
    number2:=13220198866
    //strconv.Itoa()只能转换int类型
    fmt.Println(strconv.Itoa(number2))

不同进制之间的转换

人类使用10进制计算,计算机使用二进制(一大堆0和1)进行运算。

通常计算机使用八进制和十六进制去更精简地显示二进制给人类看。 

既然人类熟悉10进制,那么把二进制转换成10进制给人类显示,岂不更方便?

因为10进制不如8进制和16进制那样,在计算机中方便运算。

 1.十进制(整型)转换成 二进制、八进制、十六进制

 在go语言中十进制是以整型的方式存在,其进制(二进制、八进制、十六进制)均已字符串的形式存在。

	var n1 int64 =190
	//十进制转换成二进制
	binaryNumber:=strconv.FormatInt(n1,2)
	fmt.Println(binaryNumber)//string
	fmt.Println(reflect.TypeOf(binaryNumber))
	//十进制转换成8进制
	octalNumber:=strconv.FormatInt(n1,8)
	fmt.Println(octalNumber)//string
	fmt.Println(reflect.TypeOf(octalNumber))
	//十进制转成16进制
	hexadecimalNumber:=strconv.FormatInt(n1,16)
	fmt.Println(hexadecimalNumber)
	fmt.Println(reflect.TypeOf(hexadecimalNumber))//string

2.二进制、八进制、十六进制(字符串)转换成十进制(int64位整型)  

我们使用strconv.Format(十进制,想要的进制 ),可以把十进制(整型)转成二进制、八进制、十六进制的字符串。

使用strconv.ParseInt(), 把二进制、八进制、十六进制(字符串)转换成十进制(整型)。

    var barnaryNumber,octalNumber,hexadecimalNumber string ="10111110","276","be"
    fmt.Println(strconv.ParseInt(barnaryNumber,2,16))
    //2:把字符串barnaryNumber当做二进制去转换成十进制,
    //16:转换过程中对十进制结果数字大小范围进行约束
    //result永远以int64的类型返回
    fmt.Println(strconv.ParseInt(octalNumber,8,16))
    fmt.Println(strconv.ParseInt(hexadecimalNumber,16,16))

 常见的数学运算

package main
import (
    "fmt"
    "math"
func main() {
    fmt.Println(math.Abs(-19))    //获取绝对值:19
    fmt.Println(math.Floor(3.14)) //向下取整
    fmt.Println(math.Ceil(3.14))  //向上取整
    fmt.Println(math.Round(3.1678)) //自动(四舍五入)取整数
    fmt.Println(math.Round(3.1678*100)/100)//自动保留小数点后2位
    fmt.Println(math.Mod(11, 3))  //获取余数
    fmt.Println(math.Pow(2, 2))   //求2的2次方
    fmt.Println(math.Pow10(2))    //求2的10次方
    fmt.Println(math.Max(3, 5))   //获取较大
    fmt.Println(math.Min(3, 5))   //获取较小

超大数值整型

当我们要使用的数字超过了64位可以表示的范围,可以使用big.Int。

package main
import (
    "fmt"
    "math/big"
func main() {
    //1.创建1个超大整型的对象
    var v1 big.Int
    //var v2 *big.Int
    v3:=new(big.Int)
    //2.在超大整型对象中写入1些值
    v1.SetInt64(1993)
    //支持以字符串的形式写入到内存,以10进制的形式
    v1.SetString("9012308480889",10)
    v3.SetString("10000000000000000000",10)
    fmt.Println(v1,v3)
    //3.超大整型操作(加减乘除)
    n1:=new(big.Int)
    n1.SetString("19999999991111",10)
    n2:=new(big.Int)
    n2.SetString("7777777777",10)
    result:=new(big.Int)
    result.Add(n1,n2)
    fmt.Println(result)
    result.Sub(n1,n2)
    fmt.Println(result)
    result.Mul(n1,n2)
    fmt.Println(result)
    result.Div(n1,n2)
    fmt.Println(result)
    //除:得到商和余数 求页码时使用
    minder:=new(big.Int)
    result.DivMod(n1,n2,minder)
    fmt.Println(result,minder)
    //把bigint转换成int64
    fmt.Println(result.Int64())
    //把bigint转换成字符串
    fmt.Println(result.String())

 int、uint、rune、byte

在Go语言中数字的默认数据类型是int类型,也就是有符号整型,如果是32的操作系统就是int32如果是64位操作系统就是int64

package main
import (
	"fmt"
	"unsafe"
func main() {
	var n1 = 100
	//n1的数据类型:int n1占用的字节数是8我的电脑是64位所以就是 int64 8位=1字节=8字节
	fmt.Printf("n1的数据类型:%T n1占用的字节数是%d \n", n1, unsafe.Sizeof(n1))
	//在程序运行中,尽量使用占用空间减少的数据类型 比如年龄的数字范围1-200足矣,不需要用int64
	var age byte = 19
	println(age)

整型变量的声明方式

为什么每中编程语言都有数据类型?

就是可以满足我们声明多样化的数据结构变量的需求,我们的程序逻辑可以处理各种各样的变量(数据)时,我们就可以完成更多的功能。

package main
import "fmt"
func main(){
	//方法1:先声明再赋值
	var n1 int32
	n1=10
	//方法2:var 声明时一起赋值
	var n2 int8 =10
	//方法3:简短声明自动推断19为默认为int类型
	n3:=18
	//方法4:int类型强制转换为int16
	var n4=int16(19)
	fmt.Printf("%T,%T,%T,%T",n1,n2,n3,n4)

浮点型为什么无法精准表示?

计算机只认识0和1,想要明白这个问题,得说到浮点型是怎么转换成二进制进行存储的。

例如:声明1个变量   var price float32 =39.29

第一步:把浮点型 39.29转换成二进制

整数部分(39/十进制)直接转换成二进制:39----->100111

小数部分:让小数乘2,结果小于1则继续乘2,如果大于1则让结果减1再继续乘2,一直等到*2=1则结束。

得出浮点型,小数部分的二进制

结果的整数部分拼接起来,所以0.29的二进制就是---->01001010001111010111000........................

问题就出在这:39.29的小数部分0.29,这特么永远得不出1,导致fraction位无法完整存储浮点型小数部分的二进制!丢失精度了!

但是有的小数是可以的例如:0.5所以并不是所有小数都会出现精度丢失的问题。

经过以上步骤39.29的二进制就100111.01001010001111010111000........................

第二步:科数据计数法表示二进制

科数计数法就是把1个数字变成1.x乘2的多少次方。向左移了几位就是2的几次方,如果向右移了几位就是2的负几次方。

科数计数法发表示:100111.01001010001111010111000........................

第三步:存储到科学计数法表示的二进制

以flaot32位进行表示

sign:表示浮点型的正负,0表示正数、1表示负数

exponent(指数):存储科学技术法的指数(几次方),exponent有8位所以表示范围=-128至127,这8位既可以表示负指数  也可以表示正值数。

例如:指数是5 那么5得+127。

为什么+5得加127,因为如果再来个是1个-5,岂不是和+5表示重叠了!

5+127=132转换乘二进制10000100存储到exponent.

fraction(小数):存储浮点型小数部分二进制的01001010001111010111000........................超出32/64位直接丢弃!这就是浮点型无法精确表示的原因。

decimal第三方包精确表示浮点型

尤其是面向电商领域开发,特别需要浮点型。

你就不得不解决浮点型精度丢失的问题,golang的decimal包可以解决这个问题。

package main
import (
    "fmt"
    "github.com/shopspring/decimal"
func main() {
    var v1 =decimal.NewFromFloat(0.0000019)
    var v2 =decimal.NewFromFloat(0.298766)
    var v3 =v1.Add(v2)
    var v4 =v3.Sub(v2)
    var v5 =v4.Mul(v2)
    var v6 =v4.Div(v1)
    fmt.Println(v3)
    fmt.Println(v4)
    fmt.Println(v5)
    fmt.Println(v6)
    var price=decimal.NewFromFloat(3.6615926)
    fmt.Println(price.Round(1)) //保留小数点后1位自动四舍五入
    fmt.Println(price.Truncate(2))//保留小数点后2位不需要四舍五入

coplex128

complex64

Go里面的布尔值不能像Python那样和0和1做转换

false

func main() {
    //字符串转换成布尔类型
    // "1", "t", "T", "true", "TRUE", "True"都可以转换成true
    //"0", "f", "F", "false", "FALSE", "False" 都可以转换成false
    reslut,err:=strconv.ParseBool("True")
    fmt.Println(reslut,err)
    //布尔类型转换成字符串
    reslut1:=strconv.FormatBool(true)
    fmt.Println(reslut1)

Go语言的字符有以下两种:

  • 一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符的编码。 
  • 另一种是 rune 类型,代表一个 UTF-8 字符的编码,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型
  • Go的字符串是由Utf-8编码之后的字节序列,所以不能修改,1个汉字占用3个字节、1个英文字母占用1个字节的存储空间。

    go使用rune(1个int32类型的数字) 表示中文字符,使用byte(1个uint8类型的数字)表示英文。

    字节切片和rune切片的区别是:

    rune切片直接存储Unicode(ucs4)中字符串对应的码位,字节切片则存储码位被utf-8编码之后的utf8码。

    package main
    import (
        "fmt"
        "strconv"
        "unicode/utf8"
    func main() {
        //1.go语言中的字符串本质上是utf-8编码之后的字节序列
        var name string="张根"
        fmt.Println(name)
        //utf-8的第三个模板:1110XXXX 10XXXXXX 10XXXXXX
        //张 utf-8码=根据张字符在Unicode的码位codepoint进行utf-8编码所得 1110【0101】 10【111100】 10【100000】
        fmt.Println(strconv.FormatInt(int64(name[0]),2),strconv.FormatInt(int64(name[1]),2),strconv.FormatInt(int64(name[2]),2))  //
        //根 utf-8码=根据张字符在Unicode的码位codepoint进行utf-8编码所得 11100110 10100000 10111001
        fmt.Println(strconv.FormatInt(int64(name[3]),2),strconv.FormatInt(int64(name[4]),2),strconv.FormatInt(int64(name[5]),2))
        //2.获取字符串的长度其实就是获取utf-8编码之后字节的长度。即6个字节
        fmt.Printf("字节长度%d\n",len(name))
        //3.字符串转换成---》1个字节切片
        byteSlice:=[]byte(name)
        fmt.Println(byteSlice)
        //4.字节切片转换成----》1个字符串
        togetByteSlice:=[]byte{229,188,160,230,160,185}
        togetString:=string(togetByteSlice)
        fmt.Println(togetString)
        //5.rune也是golang里的1种数据类型:它表示的的是字符串在Unicode(ucs4)字符集中对应的码位
        runeSet:=[]rune(name)  //[24352 26681]
        fmt.Println(runeSet)
        //张 在Unicode字符集中的码位:二进制:10111110  0100000 十六进制:5f20
        //utf-8编码的机制:(101)(111100)(100000)--->1110XXXX 10XXXXXX 10XXXXXX  --->1110【0101】 10【111100】 10【100000】
        fmt.Println(strconv.FormatInt(int64(runeSet[0]),2))
        fmt.Println(strconv.FormatInt(int64(runeSet[0]),16))
        //根 在Unicode字符集的的码位:二进制:11010000 0111001    十六进制:6839
        fmt.Println(strconv.FormatInt(int64(runeSet[1]),2))
        fmt.Println(strconv.FormatInt(int64(runeSet[1]),16))
        //6.rune切片转换成字符串
        runeList:=[]rune{24352,26681}
        fmt.Println(string(runeList)) //张根
        //7.获取字符串的字面长度 牛魔王 3个长度
        nickName:="牛魔王"
        runeLenth:=utf8.RuneCountInString(nickName)
        fmt.Println(runeLenth)
    golang字符串底层实现原理
    

    Python字符串的index方法:

    a="1111"
    print((a.index("2")))

    #找不到指定的元素Python报错:ValueError: substring not found

    Golang字符串中的strings.index()方法:

    package main
    import (
    	"fmt"
    	"strings"
    func main() {
    	testString := "Hello"
    	index := strings.Index(testString,"W")
    	fmt.Println(index)//找不到指定元素返回-1
    

    practice

    自定义1个string的split方法

    package main
    import (
    	"fmt"
    	"strings"
    func main() {
    	str1 := "123a456a789"
    	sep := "a"
    	var ret []string
    	//a的index
    	index := strings.Index(str1, sep)
    	//知道字符串中不包含a也就是index=-1为止
    	for index >= 0 {
    		//a位置之前的部分:123
    		ret = append(ret, str1[:index])
    		//a位置之后的部分:456a789
    		str1 = str1[index+1:]
    		index = strings.Index(str1, sep)
    	ret = append(ret, str1)
    	fmt.Println(ret)
        fmt.Println(utf8.RuneCountInString(name))
        //2.判断字符串开头?
        if strings.HasPrefix(name,""){
            fmt.Print("我姓张")
        //3.判断字符串结尾?
        if strings.HasSuffix(name,""){
            fmt.Print("名根。\n")
        //3.判断字符串是否包含?
        str1:="抬老子的意大利炮来。"
        if (strings.Contains(str1,"老子")){
            fmt.Println("别说脏话!")
        //4.字符串小大写转换:验证码对大小写不敏感
        realName:="Martin"
        upperName:=strings.ToUpper(realName)
        fmt.Println(upperName)
        LowerName:=strings.ToLower(upperName)
        fmt.Println(LowerName)
        //5.去除2边、 前缀、后缀
        string2:="ABC"
        result2:=strings.TrimRight(string2,"C")
        fmt.Println(result2)
        result3:=strings.TrimLeft(string2,"A")
        fmt.Println(result3)
        string3:=" ABC"
        //ps.去除两端的空格:在Python和JS中trim()没有参数自动去除空,但是go语言需要,写上空字符串
        result4:=strings.Trim(string3," ")
        fmt.Println(result4)
        //6.字符串替换
        string4:="zhanggen"
        //从左到右找到第1个进行替换
        result5:=strings.Replace(string4,"g","G",1)
        fmt.Println(result5)
        //从左到右找到前2个”g“进行替换
        result6:=strings.Replace(string4,"g","G",2)
        fmt.Println(result6)
        //替换所有“2”
        result7:=strings.Replace(string4,"n","N",2)
        fmt.Println(result7)
        //7.字符串分割成string切片
        string5:="1 2 3"
        result8:=strings.Split(string5," ")
        fmt.Println(result8,reflect.TypeOf(result8)) //[]string
        //8.字符串拼接
        //+不建议
        message:="我爱北京"+"天安门"
        fmt.Println(message)
        //效率高一些
        stringList:=[]string{"","","北京"}
        result9:=strings.Join(stringList,"")
        fmt.Println(result9)
        //效率更高一些: go 1.10之前
        var buffer bytes.Buffer
        buffer.WriteString("我爱")
        buffer.WriteString("北京")
        buffer.WriteString("天安门")
        result10:=buffer.String()
        fmt.Println(result10)
        //效率更高一些: go 1.10之后
        var builder strings.Builder
        builder.WriteString("我爱")
        builder.WriteString("")
        builder.WriteString("")
        result11:=builder.String()
        fmt.Println(result11)
        //9.字符串和整型之间相互转换:Atoi/ItoO
        var message1 string ="666"
        number,err:=strconv.Atoi(message1)
        if err==nil{
            fmt.Println(number,reflect.TypeOf(number))
        fmt.Println(strconv.Itoa(number),reflect.TypeOf(strconv.Itoa(number)))
        //字符串转数字:64:转换过程中对十进制结果数字大小范围进行约束
        number1,err:=strconv.ParseInt("1111000",2,64)
        fmt.Println(number1,err,reflect.TypeOf(number1))
        //10进制转2进制
        decimalDigit:=strconv.FormatInt(int64(120) ,2,)
        fmt.Println(decimalDigit)
        //10.字符串和字节切片之间的转换
        name2:="张纪中"
        //字符串转换成字节集合:字节切片本质上是二进制但是以10进制的方式显示出来。
        byteSet:=[]byte(name2)
        fmt.Println(byteSet)
        //字节集合转换成字符串
        byteList:=[]byte{229,188,160,231,186,170,228,184,173}
        fmt.Println(string(byteList))
        //11.字符串和rune切片之间的转换
        name3:="张艺谋"
        runeSet:=[]rune(name3)
        fmt.Println(runeSet)
        //rune int32的别名
        runeSlice:=[]rune{24352,33402,35851}
        fmt.Println(string(runeSlice))
        fmt.Println()
        //12.string和字符:根据Unicode的码位进行转换(应用生产随机验证码)
        v1:=string(26681)
        fmt.Println(v1,reflect.TypeOf(v1))
        //字符串转数字
        v2,size:=utf8.DecodeRuneInString("A")
        fmt.Println(v2,size) //65 1个字节表示1个英文字符
        v3,size:=utf8.DecodeRuneInString("")
        fmt.Println(v3,size) //26681 3个字节表示1个汉字
    字符串常见操作
    
    package main
    import (
    	"fmt"
    	"strings"
    	"unicode"
    func main() {
    	s1 := "D:\\goproject\\src"
    	//字符相关操作
    	//字符串长度
    	fmt.Println(len(s1))
    	//字符串拼接
    	FirstName := "Martin"
    	LastName := "Zhang"
    	FullName := FirstName + LastName
    	fmt.Println(FullName)
    	FullName2 := fmt.Sprintf("%s%s", LastName, FirstName)
    	fmt.Println(FullName2)
    	//字符串分割
    	s3 := "D:\\goproject\\src"
    	ret := strings.Split(s3, "\\")
    	fmt.Println(ret)
    	fmt.Println(strings.Contains(s3, "D"))
    	//判断字符串 的开头和结尾判断
    	fmt.Println(strings.HasPrefix(s3, "D"))
    	fmt.Println(strings.HasSuffix(s3, "src"))
    	//判断字符在字符串中的index
    	s2 := "abcdeb"
    	fmt.Println(strings.Index(s2, "b"))
    	fmt.Println(strings.LastIndex(s2, "b")) //最后1次出现的位置
    	//字符串拼接
    	s4 := "D:\\goproject\\src"
    	ret4 := strings.Split(s4, "\\")
    	s5 := strings.Join(ret4, "/")
    	fmt.Println(s5)
    	//字符串表里
    	//字符:组成字符串的每1个元素 我们称之为字符,在go语言里通过''单引号来定义字符
    	//在go语言里字符分为2种:1种是byte 1种是rune
    	//byte:给ascii 编码的字符起的别名
    	//rune:给Unicode编码的字符起的别名
    	var c1 byte = 'c'
    	var c2 rune = '中'
    	fmt.Printf("c1:%T c2:%T\n", c1, c2)
    	s6 := "hello 张根"
    	//for 循环 按照1个字节循环(会出现乱码:因为中文和英文占用的字节不一致)
    	// for i := 0; i < len(s6); i++ {
    	// 	fmt.Printf("%c\n", s6[i])
    	//for range 按1个字符循环
    	for _, v := range s6 {
    		fmt.Printf("%c\n", v)
    	//字符串修改
    	s7 := "白萝卜"
    	s8 := []rune(s7) //把字符串强制转换为runne切片就可以修改字符串了
    	s8[0] = '红'      //修改第一个字符
    	fmt.Println(string(s8))
    	//类型转换
    	n := 10
    	var f float64
    	f = float64(n) //整型 转成 float64类型
    	fmt.Println(f)
    	fmt.Printf("%T\n", f) //float64
    	//判读数据类型
    	s9 := "Hello张根"
    	for _, v := range s9 {
    		if unicode.Is(unicode.Han, v) {
    			fmt.Print(string(v))
    

     字符串的索引和循环遍历

    Golang的字符串和Python中的字符串存储机制上有很大区别,Python中的字符串直接是Unicode中的字符,直接同过索引获取即可。(学的这里我仿佛感受到了Python其实帮我们做了很多很多事情....)

    Golang中字符串是utf-8编码之后的字节序列,所以我们通过索引获取到的是字节(其实是一堆utf-8编码之后的0和1,显示是按10进制显示出来的)并非字符本身。

    runn 切片可以帮我们解决这种问题,如果把1个字符串转换成rune切片那么这个rune切片中就存储了字符串中每1个字符在Unicode字符集中对应的码位。

    既然得到每1个字符的码位 就好比1个工作在凌晨3点的程序员得到了老板让先下班回家的指令, 好比拿到了数据库里1个记录的index,string(codepoint)就可以拿到字符了。

    package main
    import "fmt"
    func main() {
        //1.索引获取字节
        var name= "大根子"
        //获取字字节序列的第1个字节
        fmt.Println(name[0])
        //第2个
        fmt.Println(name[1])
        //第3个
        fmt.Println(name[2])
        //2.获取字节区间:获取3个字节
        fmt.Println(name[0:3]) //
        //3.循环获取蓑鲉字节
        for i:=0;i<len(name);i++{
            fmt.Println(i,name[i])
        //4.for range获取所有字符,
        //for range字符串相当于把字符串转换成了rune切片,进行循环
        for index,item:=range name{
            fmt.Println(index,string(item))
        //5.转成rune集合获取字符
        dataList:=[]rune(name)
        fmt.Println(dataList[0],string(dataList[0]))
    字符串正确的索引和循环方式
    

     字符(char)

    在Go中有字符的概念,使用单引号表示,需要注意的是,英文字符和中文字符,

    Go 使用int 的 数据类型别名的方式来表示字符。其中rune为int32的数据类型别名表示中文byte为uint8的数据类型别名用于表示英文

    什么是数据类型别名?

    In a nutshell just an other name name data type of Golang by you like way.

    。。...

    package main
    import "fmt"
    var c1 byte = 'c'
    var c2 rune = '中'
    type myInt = int
    func main() {
    	var n myInt
    	n = 100
    	fmt.Printf("%T\n",n)//%T\n Myint还是int
    	fmt.Printf("%T\n", c1) //uint8
    	fmt.Printf("%T\n", c2) //int32