前言

程序=数据+指令(算法)所以数据结构就是帮我们 解决  如何在程序开发过程  定义和存储要用到的数据;

Go语言的数据类型拥有丰富的数据类型

 

 Golang基础数据类型(整型、浮点型、字符串、布尔)

 

 

整型

.\main.go:8:21: constant 1000 overflows uint8

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

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

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

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

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

综上所述:

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

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

 

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

 Golang基础数据类型(整型、浮点型、字符串、布尔)

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

 Golang基础数据类型(整型、浮点型、字符串、布尔)

 

有符号整型:

 Golang基础数据类型(整型、浮点型、字符串、布尔)

 

int8、int16、int32、int64

 

无符号整型:

Golang基础数据类型(整型、浮点型、字符串、布尔)

 

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))

 

不同进制之间的转换

Golang基础数据类型(整型、浮点型、字符串、布尔)

人类使用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

 Golang基础数据类型(整型、浮点型、字符串、布尔)

 

在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)

}

  

 

浮点型

Go语言提供了2种浮点型float32和float64, 默认使用float64。 单fudi

Golang基础数据类型(整型、浮点型、字符串、布尔)

float32

float64  

 

我们平时使用的这些编程语言处理小数时 表示是不精准的。

JavaScript

Golang基础数据类型(整型、浮点型、字符串、布尔)

Python

Golang基础数据类型(整型、浮点型、字符串、布尔)

 Golang

v1:=0.1
v2:=0.2
fmt.Println(v1+v2) //0.30000000000000004 

 

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

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

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

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

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

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

Golang基础数据类型(整型、浮点型、字符串、布尔)

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

Golang基础数据类型(整型、浮点型、字符串、布尔)

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

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

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

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

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

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

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

Golang基础数据类型(整型、浮点型、字符串、布尔)

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

以flaot32位进行表示

Golang基础数据类型(整型、浮点型、字符串、布尔)

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

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

例如:Golang基础数据类型(整型、浮点型、字符串、布尔)指数是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做转换

true

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字符串底层实现原理

相关文章:

  • 2022-12-23
  • 2021-11-15
  • 2021-05-24
  • 2021-12-01
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-09-27
  • 2021-11-06
  • 2022-12-23
  • 2022-12-23
  • 2021-11-05
  • 2021-09-28
相关资源
相似解决方案