03-Go语言基础之基本数据类型
Go整型
Go语言的数值类型包含不同大小的整数型、浮点数和负数,每种数值类型都有大小范围以及正负符号。
整型的使用
- golang整数类型分为有符号和无符号
- golang默认整型是int型
整型分为以下两个大类:
按长度分为:int8、int16、int32、int64
对应的无符号整型:uint8、uint16、uint32、uint64
uint8就是我们熟知的byte型
| 类型 | 描述 |
|---|---|
| uint8 | 无符号 8位整型 (0 到 255) |
| uint16 | 无符号 16位整型 (0 到 65535) |
| uint32 | 无符号 32位整型 (0 到 4294967295) |
| uint64 | 无符号 64位整型 (0 到 18446744073709551615) |
| int8 | 有符号 8位整型 (-128 到 127) |
| int16 | 有符号 16位整型 (-32768 到 32767) |
| int32 | 有符号 32位整型 (-2147483648 到 2147483647) |
| int64 | 有符号 64位整型 (-9223372036854775808 到 9223372036854775807) |
不同整型用于存储不同场景的数据,了解即可。
特殊整型
| 类型 | 描述 |
|---|---|
| uint | 32位操作系统上就是uint32,64位操作系统上就是uint64 |
| int | 32位操作系统上就是int32,64位操作系统上就是int64 |
| uintptr | 无符号整型,用于存放一个指针 |
数字字面量语法(Number literals syntax)
Go1.13版本之后引入了数字字面量语法,这样便于开发者以二进制、八进制或十六进制浮点数的格式定义数字。
而且还允许我们用 _ 来分隔数字,比如说: v := 123_456 表示 v 的值等于 123456。
整型案例
package main
import "fmt"
func main() {
// 默认根据你机器系统架构来,64为机器,就是int64
var n1 = 100
// n1的类型:int
fmt.Printf("n1的类型:%T \n", n1)
// 也可以指定整型类型,但是要注意赋值范围
var n2 int8 = 127
var n3 uint8 = 0
var n4 int64 = -123456789
// 一般开发,定义整型关心不到这些区别,了解即可
// 127 0 -123456789
fmt.Println(n2, n3, n4)
// 还有一些额外的知识点,定义不同进制的整型语法 ,叫做数字字面量语法(Number literals syntax)
// 便于开发者,定义二进制、八进制、十六进制等格式的数字,使用场景也较少,了解做笔记即可
var (
i1 = 10 // 十进制
i2 = 0b1010 // 二进制
i3 = 0xa // 十六进制
i4 = 1234_56_789 //支持数字里以_分割,看起来,例如银行里的余额 1,000元 看起来清晰
)
fmt.Println(i1, i2, i3, i4)
// 也可以利用fmt的格式化打印,获取不同进制的结果
// 格式化打印
res1 := 10
fmt.Println("该函数自带换行")
fmt.Printf("十进制:%d \n", res1)
fmt.Printf("二进制:%b \n", res1)
fmt.Printf("八进制:%o \n", res1)
fmt.Printf("十六进制:%x \n", res1)
}
Go浮点型
Go 语言提供了两种精度的浮点数,float32 和 float64,编译器默认声明为float64
小数类型就是存放小数的,如1.2 0.005 -2.32
注意,计算机的浮点数是不精准的,实际处理工作业务遇见浮点数运算一般都是转成整型后处理。
| 类型 | 占用存储空间 | 数值范围 |
|---|---|---|
| 单精度float32 | 4字节 | -3.4e38~3.4e38 |
| 双精度float64 | 8字节 | -1.8E308 ~ 1.8e308 |
package main
import (
"fmt"
"math"
)
func main() {
var price float32 = 11.22 //正数符号
fmt.Println("price=", price)
var num1 float32 = -3.4 //负数符号
var num2 float64 = -8.23
fmt.Println("num1=", num1)
fmt.Println("num2=", num2)
//尾数可能丢失,精度缺损
var num3 float32 = -123.11111111105 //精度丢失了
var num4 float64 = -123.11111111105 //float64的精度高于float32
fmt.Println("num3=", num3, "num4=", num4)
//输出结果
//num3= -123.111115 num4= -123.11111111105
// 可以用math数学模块,打印浮点数看看
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi) // 保留2位小数
fmt.Printf("%f\n", math.MaxFloat64)
fmt.Printf("%f\n", math.MaxFloat32)
}
结果
➜ goStudy go run main.go
price= 11.22
num1= -3.4
num2= -8.23
num3= -123.111115 num4= -123.11111111105
3.141593
3.14
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
340282346638528859811704183484516925440.000000
Go布尔型
一个布尔类型的值只有两种:true 和 false。
注意的是
- if 和 for 语句的条件部分都是布尔类型的值,并且==和<等比较操作也会产生布尔型的值。
- 布尔值变量默认值是false
- Go语言不允许整型转布尔值,不同于其他语言。
- 布尔值无法参与运算,也无法转换。
package main
import (
"fmt"
"unsafe"
)
func main() {
var t = true
fmt.Println("t=", t)
fmt.Println("t字节数=", unsafe.Sizeof(t))
var f = false
fmt.Println("f=", f)
fmt.Println("f字节数=", unsafe.Sizeof(f))
//默认布尔值
var b bool
fmt.Printf("变量b类型:%T,变量b值:%v\n", b, b)
}
/*
结果
t= true
t字节数= 1
f= false
f字节数= 1
变量b类型:bool,变量b值:false
*/
Go格式化输出fmt包语法
# 用于fmt.Printf()的格式化语法
# 通用:
%v 值的默认格式表示。当输出结构体时,扩展标志(%+v)会添加字段名
%#v 值的Go语法表示
%T 值的类型的Go语法表示
%% 百分号
布尔值:
%t 单词true或false
整数
%b 表示为二进制
%c 该值对应的unicode码值
%d 表示为十进制
%o 表示为八进制
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%x 表示为十六进制,使用a-f
%X 表示为十六进制,使用A-F
%U 表示为Unicode格式:U+1234,等价于"U+%04X"
浮点数、复数
%b 无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat
%e 科学计数法,如-1234.456e+78
%E 科学计数法,如-1234.456E+78
%f 有小数部分但无指数部分,如123.456
%F 等价于%f %g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
字符串、字符
%s 直接输出字符串或者[]byte
%q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x 每个字节用两字符十六进制数表示(使用a-f)
%X 每个字节用两字符十六进制数表示(使用A-F)
指针
%p 表示为十六进制,并加上前导的0x
Go字符串
字符串处理是任何一门语言的重点内容
- Go字符串是一个不可改变的字节序列
- Go字符串通常用来表示人类可阅读的文本数据
- Go字符串默认编码使用UTF-8
- Go字符串的值,必须是双引号
www.yuchaoit.cn
字符串转义符
Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。
| 转义符 | 含义 |
|---|---|
\r |
回车符(返回行首) |
\n |
换行符(直接跳到下一行的同列位置) |
\t |
制表符 |
\' |
单引号 |
\" |
双引号 |
\\ |
反斜杠 |
字符串综合练习
package main
import "fmt"
func main() {
// 声明字符串类型
var story string = "努力学习是为了提升你的抗风险能力"
fmt.Println(story)
// 简短声明
filename := "/var/log/nginx/access.log"
fmt.Printf("filename类型:%T,filename值:%v\n", filename, filename)
//Go字符串能识别特殊符号,可以使用转义符
story2 := "妖怪\n还不快快放了我\"大哥\"!"
fmt.Println(story2)
// Go字符串里使用 反引号,以原生字符串形式输出,不解析任何特殊字符,防止如注入攻击等
story3 := `那年我
双手插兜,
不知道什么叫做\n对手!`
fmt.Println(story3)
//Go字符串是不可修改的
story4 := "hello world"
//story4[1]='x' 错误,不允许修改
fmt.Printf("第2个字符:%c\n", story4[1])
// 数数字符串,有多少个字符(长度)
// 一个中文占3个英文字母长度
story5 := "hello world哈"
fmt.Println("story5字符串长度:", len(story5))
//Go字符串拼接
s1 := "刘德华"
s2 := "春节快乐"
fmt.Println(s1 + "--" + s2)
//按格式,格式化字符串且返回最终结果
res := fmt.Sprintf("大家好,%s祝大家%s!", s1, s2)
fmt.Println(res)
//Go多行字符串拼接,注意结尾的+号
s3 := "你" + "总该" + "为自己" +
"想想未来" + "!"
fmt.Println(s3)
//Go for循环遍历字符串
s4 := "helloWorld"
for index, ret := range s4 {
fmt.Printf("index---%v,ret--%c\n", index, ret)
}
// Go也能实现修改字符串,这里先不做了解,还需要学完slice切片类型
myname := "hello world"
m1 := []rune(myname) //转化为[]int32的切片,rune是int32的别名
m1[4] = '皮' //修改索引对应的值
myname = string(m1) //类型强转,rune转为string
fmt.Println(myname)
}
/*
➜ goStudy go run main.go
努力学习是为了提升你的抗风险能力
filename类型:string,filename值:/var/log/nginx/access.log
妖怪
还不快快放了我"大哥"!
那年我
双手插兜,
不知道什么叫做\n对手!
第2个字符:e
story5字符串长度: 14
刘德华--春节快乐
大家好,刘德华祝大家春节快乐!
你总该为自己想想未来!
index---0,ret--h
index---1,ret--e
index---2,ret--l
index---3,ret--l
index---4,ret--o
index---5,ret--W
index---6,ret--o
index---7,ret--r
index---8,ret--l
index---9,ret--d
hell皮 world
*/
字符串处理strings包
https://pkg.go.dev/strings 官网教程
一个内置的提供了对字符串诸多功能处理的包,有很多函数可用。
package main
import (
"fmt"
"strings"
)
func main() {
url1 := "http://www.yuchaoit.cn"
//判断字符串是否以xx开头,返回布尔值
res := strings.HasPrefix(url1, "https://")
res2 := strings.HasPrefix(url1, "http://")
fmt.Println("该url复合https吗?", res)
fmt.Println("该url符合http吗?", res2)
//判断字符串是否以xx结尾
url2 := "http://www.yuchaoit.cn/login"
res3 := strings.HasSuffix(url2, "home")
res4 := strings.HasSuffix(url2, "login")
fmt.Println("url2是home接口", res3)
fmt.Println("url2是login接口", res4)
//判断字符在字符串中首次出现的索引位置,没有返回-1
s1 := " hello world and code!"
res5 := strings.Index(s1, "o") // 索引号是4
res6 := strings.Index(s1, "x") //找不到返回-1
fmt.Printf("res5 is %v\n", res5)
fmt.Printf("res6 is %v\n", res6)
//返回字符最后一次出现的索引位置,没有返回-1
res7 := strings.LastIndex(s1, "o")
res8 := strings.LastIndex(s1, "x")
fmt.Printf("res7 is %v\n", res7)
fmt.Printf("res8 is %v\n", res8)
//字符串替换
res9 := strings.Replace(s1, "world", "golang", 2)
res10 := strings.Replace(s1, "world", "golang", 1)
//语法,strings.Replace("原字符串", "被替换的内容", "替换的内容", 替换次数)
//原字符串中有2个world,才能替换2次
fmt.Printf("res9 is %v\n", res9)
fmt.Printf("res10 is %v\n", res10)
//求字符在字符串中出现的次数,不存在返回0次
countTime0 := strings.Count(s1, "h")
countTime1 := strings.Count(s1, "l")
fmt.Printf("字符h出现次数: %v\n", countTime0)
fmt.Printf("字符l出现次数: %v\n", countTime1)
//重复几次字符串
res11 := strings.Repeat(s1, 0)
res12 := strings.Repeat(s1, 1)
res13 := strings.Repeat(s1, 2)
// strings.Repeat("原字符串", 重复次数)
fmt.Printf("res11 is :%v\n", res11)
fmt.Printf("res12 is :%v\n", res12)
fmt.Printf("res13 is :%v\n", res13)
//字符串全部大写,如验证码校验
res14 := strings.ToUpper(s1)
fmt.Printf("res14 is : %v\n", res14)
//字符串改小写
res15 := strings.ToLower(s1)
fmt.Printf("res15 is: %v\n", res15)
//去除首尾的空格,如去除用户表单提交的数据
res16 := strings.TrimSpace(s1)
fmt.Printf("res16 is :%v\n", res16)
//去除首尾指定的字符
// 在前一题,去除空格基础上再操作
res17 := strings.Trim(res16, "he") //删除头尾的h、e 字符
fmt.Printf("res17 is: %v\n", res17)
//去除开头指定的字符
res18 := strings.TrimLeft(res16, "he")
fmt.Printf("res18 is %v\n", res18)
//去除结尾指定的字符
res19 := strings.TrimRight(s1, "!")
fmt.Printf("res19 is %v\n", res19)
//用指定的字符串将string类型的切片元素结合
str1 := []string{"hello", "world", "hello", "golang"}
fmt.Println(str1) // [hello world hello golang]
res20 := strings.Join(str1, ",") //返回值是字符串
fmt.Printf("res20 is %v, 类型:%T\n", res20, res20)
}
/*
该url复合https吗? false
该url符合http吗? true
url2是home接口 false
url2是login接口 true
res5 is 7
res6 is -1
res7 is 20
res8 is -1
res9 is hello golang and code!
res10 is hello golang and code!
字符h出现次数: 1
字符l出现次数: 3
res11 is :
res12 is : hello world and code!
res13 is : hello world and code! hello world and code!
res14 is : HELLO WORLD AND CODE!
res15 is: hello world and code!
res16 is :hello world and code!
res17 is: llo world and code!
res18 is llo world and code!
res19 is hello world and code
[hello world hello golang]
res20 is hello,world,hello,golang, 类型:string
*/
Go字符
ascii码表

Go字符如何表示

"你好,我是go语言"
这个字符串是由挨个的'字符'组成,我们可以for遍历字符串,得到单个的字符
字符在go语言里用单引号包裹,如 '你'
Go语言表示字符有两个方式
1. uint8类型,也叫做byte类型,代表一个ASCII码字符, uint8整数范围0~255
2. rune类型,代表一个UTF-8编码字符 ,而int32可表示的字符就多了, 毕竟范围-2147483648 到 2147483647
一般要处理中文,日文等复杂字符时,就用到了rune类型
3.UTF-8编码表下的中文汉字,是由3~4个字节组成,因此for遍历中文字符串,需要额外处理。
4.Go字符串底层是用 []byte数组存储。
Go字符实践
package main
import "fmt"
func main() {
// 默认都用int32去存字符了,也就是rune类型,因为go默认编码是utf-8
var a = 'y'
var b = 'c'
var c = '于'
fmt.Printf("a 类型:%T,值:%c\n", a, a)
fmt.Printf("b 类型:%T,值:%c\n", b, b)
fmt.Printf("c 类型:%T,值:%c\n", c, c)
//也可以自己去指定 byte类型,也就是uint8
var c1 byte = 'a'
var c2 byte = '2'
//直接输出byte的值,也就是输出对应的字符的ascii码值
fmt.Println("c1=", c1)
fmt.Println("c2=", c2)
//输出字符的值,需要格式化输出
fmt.Printf("c1值=%c c1类型=%T\n", c1, c1)
fmt.Printf("c2值=%c c1类型=%T\n", c2, c2)
}
/*
a 类型:int32,值:y
b 类型:int32,值:c
c 类型:int32,值:于
c1= 97
c2= 50
c1值=a c1类型=uint8
c2值=2 c1类型=uint8
*/
Go字符串如何修改

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。
字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。
rune类型用来表示utf-8字符,一个rune字符由一个或多个byte组成。
修改中文字符串
package main
import "fmt"
func main() {
hobby := "书中自有黄金屋"
//先进行类型强转,字符串可以直接转成 []byte 或者 []rune 前提看你转的是中文,还是英文
runeHobby := []rune(hobby)
// []int32,值 [20070 20013 33258 26377 40644 37329 23627] 里面的数字就是对应的utf-8编码表的值
fmt.Printf("runeHobby类型:%T,值%v\n", runeHobby, runeHobby)
//数组是可以修改的,如
runeHobby[0] = '梦'
fmt.Printf("修改后runeHobby类型:%T,值%v\n", runeHobby, runeHobby)
// []rune 再转为 string类型
hobby = string(runeHobby)
fmt.Printf("新字符串hobby类型:%T,%v\n", hobby, hobby)
}
修改英文字符串
package main
import "fmt"
func main() {
hobby := "helloworld"
//先进行类型强转,字符串可以直接转成 []byte 或者 []rune 前提看你转的是中文,还是英文
byteHobby := []byte(hobby)
fmt.Printf("byteHobby类型:%T,值%v\n", byteHobby, byteHobby)
//数组是可以修改的,如
byteHobby[0] = 'H'
fmt.Printf("修改后byteHobby类型:%T,值%v\n", byteHobby, byteHobby)
// []rune 再转为 string类型
hobby = string(byteHobby)
fmt.Printf("新字符串hobby类型:%T,%v\n", hobby, hobby)
}
/*
byteHobby类型:[]uint8,值[104 101 108 108 111 119 111 114 108 100]
修改后byteHobby类型:[]uint8,值[72 101 108 108 111 119 111 114 108 100]
新字符串hobby类型:string,Helloworld
*/
Go类型转换
Golang在不同的数据类型之间赋值时需要显示转化,无法自动转换(没有隐式类型转换)。
并且只能在两个类型允许相互转换时使用。
语法
T(v) 将v转化为T类型
T 数据类型 如 int32 int64 float32
V 需转化的变量
类型转化注意点
1)Go中数据类型的转换可以从 数值范围大 > 数值范围小,反之也可,注意别溢出
2)被转化的变量存储的数值,变量本身的数据类型没变化
package main
import "fmt"
func main() {
var num1 int32 = 100
var num2 float32 = float32(num1) //num2强转为浮点型
fmt.Printf("num1=%v num2=%v num2类型:%T\n", num1, num2, num2) //%v 值的默认格式
fmt.Printf("num1类型是:%T", num1) //本身的类型 没有变化
}
/*
num1=100 num2=100 num2类型:float32
num1类型是:int32
*/
不同类型变量如何计算
package main
import "fmt"
func main() {
var n1 int32 = 12
var n2 int64 = 10
//n3:=n1+n2 //不同类型之间无法计算,需要强转
n3 := n1 + int32(n2)
fmt.Println(n3) // 结果 22
}
Go基本数据类型转string
字符串类型是开发过程用的最多的类型,也经常会与其他数据类型转换。
fmt.Sprintf
语法:fmt.Sprintf("%参数",表达式)
该函数返回值是string
Sprintf 根据格式说明符格式化并返回结果字符串。
package main
import "fmt"
func main() {
var num1 int = 66
var num2 float64 = 25.25
var b bool = true
var myChar byte = 'c'
//%q 该值对应的双引号括起来的Go语法字符串字面值,必要时会采用安全的转义表示
//%d 表示为十进制
// Sprintf 根据格式说明符格式化并返回结果字符串。
str1 := fmt.Sprintf("%d", num1)
fmt.Printf("str1 type %T str=%q\n", str1, str1)
//%f 有小数点
str2 := fmt.Sprintf("%f", num2)
fmt.Printf("str2 type %T str2=%q\n", str2, str2)
//%t 布尔值
str3 := fmt.Sprintf("%t", b)
fmt.Printf("str3 type %T str3=%q\n", str3, str3)
//%c Unicode码对应的字符
str4 := fmt.Sprintf("%c", myChar)
fmt.Printf("str4 type %T str4=%q\n", str4, str4)
}
strconv包
包 strconv 实现了与基本数据类型的字符串表示之间的转换。
package main
import (
"fmt"
"strconv"
)
func main() {
var num1 int = 99
var num2 float64 = 66.66
var b1 bool = true
str1 := strconv.FormatInt(int64(num1), 10)
fmt.Printf("str1类型是%T str1=%q\n", str1, str1)
//参数解释
// f 格式
// 4 小数位保留4位
// 64 表示float64
str2 := strconv.FormatFloat(num2, 'f', 4, 64)
fmt.Printf("str2类型是%T str2=%q\n", str2, str2)
str3 := strconv.FormatBool(b1)
fmt.Printf("str3类型是%T str3=%q\n", str3, str3)
//Itoa,将int转为string,注意,必须是int类型
var num3 int32 = 1123
str4 := strconv.Itoa(int(num3)) //必须强转int()
fmt.Printf("str4类型是%T str4=%q\n", str4, str4)
}