前言
程序=数据+指令(算法)所以数据结构就是帮我们 解决 如何在程序开发过程 定义和存储要用到的数据;
Go语言的数据类型拥有丰富的数据类型
整型
.\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语言中十进制是以整型的方式存在,其进制(二进制、八进制、十六进制)均已字符串的形式存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) } |
浮点型
Go语言提供了2种浮点型float32和float64, 默认使用float64。 单fudi
float32
float64
我们平时使用的这些编程语言处理小数时 表示是不精准的。
JavaScript
Python
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则结束。
得出浮点型,小数部分的二进制
结果的整数部分拼接起来,所以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做转换
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) }
Python字符串的index方法:
1 2 | a = "1111" print ((a.index( "2" )))<br><br> #找不到指定的元素Python报错:ValueError: substring not found |
Golang字符串中的strings.index()方法:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) } |
字符串相关操作
go中字符串相关的操作的API都封装在strings包中

package main import ( "bytes" "fmt" "reflect" "strconv" "strings" "unicode/utf8" ) func main() { //1.获取字符串的字面长度 name:="张根" 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.
。。...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2019-03-19 Docker相关