「Go笔记-02」变量、数据类型、数据类型间转换、进制转换...看这一篇就Go了
前言
一个程序就是一个世界,不论是使用哪种高级程序语言编写程序, 变量都是其程序的基本组成单位,
变量
在 go 中 变量是用于存储数据的命名空间(内存位置),它可以表示一个值,这个值在程序执行过程中可能会发生改变。
+-------------+ +---------------------+
| 变量名: myVar|------>| 内存地址: 0x12345678|
+-------------+ +---------------------+
| 数据值: 42 |
+---------------------+
关键概念
-
标识符(名称): 变量具有一个唯一的名称,用于在程序中引用它。变量名应遵循编程语言的命名规则,通常以字母、数字和下划线组成,并且不能以数字开头。关键字和预定义标识符可以查看附录 :附录
-
数据类型: 变量有一个与之关联的数据类型,如整数、浮点数、布尔值或自定义类型。数据类型决定了变量可以存储的值的范围和类型。
-
值: 变量表示一个值,这个值可以在程序执行过程中改变。通过赋值操作,我们可以将一个新值存储到变量中。
-
作用域: 变量在程序中的可见范围称为作用域。作用域决定了在哪些部分的代码中可以访问和修改变量。通常,局部变量在函数或代码块内部定义,全局变量在整个程序范围内定义。
-
生命周期: 变量的生命周期是从创建到销毁的过程。局部变量的生命周期通常与函数或代码块的执行周期相同;全局变量的生命周期从程序启动到程序结束。
变量的使用
- go 中 局部变量的声明方式有 4种
- go 中 全局变量的声明方式有 2 种
示例
package main
import "fmt"
// 全局变量
var globalInt = 100
var globalFloat = 9.7
// 一次性声明多个全局变量
var (
globalInt2 = 500
globalString2 = "netty"
)
func main() {
// 局部变量
// 1. 变量声明
var age int
// 2. 变量赋值
age = 18
// 3. 变量使用
fmt.Println("age =", age)
// 2、声明和赋值可以合并成一句
var age2 int = 19
fmt.Println("age2 =", age2)
// 以下代码将会报错,因为变量 age 重复声明
// var age int = 20
// fmt.Println("age =", age)
// 以下代码将会报错,因为浮点数不能直接赋值给整数类型变量
// var num int = 12.56
// fmt.Println("num =", num)
// 指定变量类型,使用默认值
var age3 int
fmt.Println(age2)
// 3、自动类型推断
var name = "tom"
fmt.Println(name)
//4、 省略 var 关键字,使用 :=
gender := "男"
fmt.Println(gender)
// 一次性声明多个局部变量
var n1, n2, n3 int
fmt.Println(n1)
fmt.Println(n2)
fmt.Println(n3)
// 一次性声明多个局部变量并赋值
var n4, name2, n5 = 10, "jack", 7.8
fmt.Println(n4)
fmt.Println(name2)
fmt.Println(n5)
// 使用 := 一次性声明多个局部变量并赋值
n6, height := 6.9, 100.6
fmt.Println(n6)
fmt.Println(height)
// 输出全局变量
fmt.Println(globalInt)
fmt.Println(globalFloat)
fmt.Println(globalInt2)
fmt.Println(globalString2)
}
数据类型
Golang
变量的数据类型包含基本数据类型和派生(复杂)数据类型:
类别 | 数据类型 | 说明 |
---|---|---|
基本数据类型 | bool | 布尔类型,值为 true 或 false |
int8, int16, int32, int64 | 有符号整数类型,分别占用 8, 16, 32, 64 位存储空间 | |
uint8, uint16, uint32, uint64 | 无符号整数类型,分别占用 8, 16, 32, 64 位存储空间 | |
int | 有符号整数类型,大小与操作系统位数相关(32 位或 64 位) | |
uint | 无符号整数类型,大小与操作系统位数相关(32 位或 64 位) | |
uintptr | 无符号整数类型,足以存储指针的大小 | |
float32, float64 | 浮点数类型,分别占用 32 位和 64 位存储空间 | |
complex64, complex128 | 复数类型,分别占用 64 位和 128 位存储空间 | |
byte | 字节类型,等同于 uint8 | |
rune | Unicode 字符类型,等同于 int32 | |
string | 字符串类型 | |
派生数据类型 | array | 固定长度的数组类型 |
slice | 可变长度的数组类型(切片) | |
map | 无序键值对集合(字典) | |
struct | 自定义数据结构(结构体) | |
interface | 定义一组方法的集合(接口) | |
pointer | 存储变量内存地址的类型(指针) | |
channel | 用于协程间通信的类型(通道) | |
function | 函数类型 |
整数类型
简单的说,就是用于存放整数值的,比如10,-45,6712等等。
有符号整数类型:
类型 | 是否有符号 | 占用空间 | 取值范围 |
---|---|---|---|
int8 | 是 | 8 位 (1 字节) | -128 到 127 (-2^7 到 2^7-1) |
int16 | 是 | 16 位 (2 字节) | -32,768 到 32,767 (-2^15 到 2^15-1) |
int32 | 是 | 32 位 (4 字节) | -2,147,483,648 到 2,147,483,647 (-2^31 到 2^31-1) |
int64 | 是 | 64 位 (8 字节) | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 (-2^63 到 2^63-1) |
PS:127怎么算出来的?
01111111 –>二进制 —》转为十进制:
1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 64 + 32 + 16 + 8 + 4 + 2 + 1
= 127
PS:-128怎么算出来的?
10000000 —>二进制 —>一看就是个负数
10000000 –》负数的二进制
减1:01111111
取反:10000000 —》得到一个正数 2^7 = 128
加负号:-128
无符号整数类型:
这些类型可用于表示不同范围的非负整数值。
类型 | 是否有符号 | 占用空间 | 取值范围 |
---|---|---|---|
uint8 | 否 | 8 位 (1 字节) | 0 到 255 (0 到 2^8-1) |
uint16 | 否 | 16 位 (2 字节) | 0 到 65,535 (0 到 2^16-1) |
uint32 | 否 | 32 位 (4 字节) | 0 到 4,294,967,295 (0 到 2^32-1) |
uint64 | 否 | 64 位 (8 字节) | 0 到 18,446,744,073,709,551,615 (0 到 2^64-1) |
表数范围的边界计算:
11111111= 2^7+127 = 128 + 127 = 255
00000000 = 0
其他整数类型
以下是一个完整的表格,将取值范围放在同一个单元格中:
类型 | 是否有符号 | 占用空间 | 取值范围 | 说明 |
---|---|---|---|---|
int | 是 | 32 位或64 位 (依赖操作系统) | 32 位: -2^31 到 2^31-1 64 位: -2^63 到 2^63-1 |
有符号整数,大小与操作系统位数相关 |
uint | 否 | 32 位或64 位 (依赖操作系统) | 32 位: 0 到 2^32-1 64 位: 0 到 2^64-1 |
无符号整数,大小与操作系统位数相关 |
uintptr | 否 | 32 位或64 位 (依赖操作系统) | 32 位: 0 到 2^32-1 64 位: 0 到 2^64-1 |
无符号整数,足以存储指针的大小 |
byte | 否 | 8 位 (1 字节) | 0 到 2^8-1 | 字节类型,等同于 uint8 |
rune | 是 | 32 位 (4 字节) | -2^31 到 2^31-1 | Unicode 字符类型,等同于 int32 |
这些类型在特定场景下(如操作系统相关编程、处理字节和 Unicode 字符)非常有用。
PS:Golang的整数类型,默认声明为int类型
查询变量占用的字节数
在 Go 语言中,可以使用 unsafe.Sizeof()
函数来查看变量占用的字节数。unsafe.Sizeof()
函数返回一个变量所占用的字节数,以 uintptr
类型表示。请注意,使用 unsafe
包可能会带来潜在的安全风险和跨平台兼容性问题,因此在使用时要谨慎。
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int32 = 10
var b float64 = 20.5
var c bool = true
var d byte = 255
var e rune = 'A'
var f string = "hello"
fmt.Printf("Size of int32: %d bytes\\n", unsafe.Sizeof(a))
fmt.Printf("Size of float64: %d bytes\\n", unsafe.Sizeof(b))
fmt.Printf("Size of bool: %d bytes\\n", unsafe.Sizeof(c))
fmt.Printf("Size of byte: %d bytes\\n", unsafe.Sizeof(d))
fmt.Printf("Size of rune: %d bytes\\n", unsafe.Sizeof(e))
fmt.Printf("Size of string: %d bytes\\n", unsafe.Sizeof(f))
}
在这个示例中,我们使用 unsafe.Sizeof()
函数查看了不同类型变量占用的字节数,并将结果打印到控制台。请注意,对于 string
类型,unsafe.Sizeof()
函数返回的值是字符串头部的大小,而不是实际字符串内容的大小。要获取字符串内容的长度,可以使用 len()
函数。
这么多整数类型,使用的时候该如何选择呢?
Golang程序中整型变量在使用时,遵守保小不保大的原则,
即:在保证程序正确运行下,尽量使用占用空间小的数据类型
浮点类型
浮点类型介绍:
简单的说,就是用于存放小数值的,比如3.14、0.28、-7.19等等。
浮点类型种类:
类型 | 是否有符号 | 占用空间 | 取值范围及精度 | 说明 |
---|---|---|---|---|
float32 | 是 | 32 位 (4 字节) | 1.18e-38 到 3.4e38(约 7 位有效数字) | 单精度浮点数 |
float64 | 是 | 64 位 (8 字节) | 2.23e-308 到 1.8e308(约 16 位有效数字) | 双精度浮点数(通常使用) |
在大多数情况下,推荐使用 float64
类型,因为它具有更高的精度和更广泛的取值范围。
PS:底层存储空间和操作系统无关
PS:浮点类型底层存储:符号位+指数位+尾数位,所以尾数位只是存了 一个大概,很可能会出现精度的损失。
示例:
package main
import "fmt"
func main() {
// 定义正的 float32 类型变量
var num1 float32 = 3.14
fmt.Println(num1)
// 定义负的 float32 类型变量
var num2 float32 = -3.14
fmt.Println(num2)
// 使用科学计数法表示的 float32 类型变量
var num3 float32 = 314e-2
fmt.Println(num3)
// 使用科学计数法表示的 float32 类型变量
var num4 float32 = 314e+2
fmt.Println(num4)
// 使用科学计数法表示的 float32 类型变量
var num5 float32 = 314e+2
fmt.Println(num5)
// 使用科学计数法表示的 float64 类型变量
var num6 float64 = 314e+2
fmt.Println(num6)
// float32 类型变量可能存在精度损失
var num7 float32 = 256.000000916
fmt.Println(num7)
// float64 类型变量具有更高的精度
var num8 float64 = 256.000000916
fmt.Println(num8)
// Go 语言中默认的浮点类型为 float64
var num9 = 3.17
fmt.Printf("num9对应的默认的类型为:%T", num9)
}
字符类型
- Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。
- Golang中字符使用UTF-8编码
- ASCII码表:
- 查询字符对应的UTF-8编码表:http://www.mytju.com/classcode/tools/encode_utf8.asp
示例:
package main
import "fmt"
func main() {
// 定义 ASCII 字符类型的数据 (byte 类型)
var char1 byte = 'a'
fmt.Println(char1) // 输出: 97
var char2 byte = '6'
fmt.Println(char2) // 输出: 54
var char3 byte = '('
fmt.Println(char3 + 20) // 输出: 40
// 字符类型本质上是一个整数,可以直接参与运算。输出时,会将对应的码值输出。
// 字母、数字、标点等字符在底层按照 ASCII 进行存储。
// 定义 Unicode 字符类型的数据 (int 类型)
var char4 int = '中'
fmt.Println(char4) // 输出: 20013
// 汉字字符在底层对应的是 Unicode 码值。
// 码值为 20013,超出 byte 类型能存储的范围,因此使用 int 类型存储。
// 总结:Go 语言的字符使用 UTF-8 编码(Unicode 是对应的字符集,UTF-8 是 Unicode 的其中一种编码方案)。
var char5 byte = 'A'
// 若要显示对应的字符,必须采用格式化输出
fmt.Printf("char5 对应的具体的字符为:%c", char5) // 输出: A
}
转义字符
转义字符 | 定义 | 作用 |
---|---|---|
\\ | 反斜杠 | 表示一个反斜杠字符 |
\' | 单引号 | 表示一个单引号字符 |
\" | 双引号 | 表示一个双引号字符 |
\n | 换行符 | 在输出中插入一个换行符 |
\r | 回车符 | 在输出中插入一个回车符,使光标移动到行首 |
\t | 制表符(水平制表符) | 在输出中插入一个制表符,用于对齐文本 |
\b | 退格符 | 在输出中插入一个退格符,使光标回退一个字符位置 |
\f | 换页符 | 在输出中插入一个换页符,使光标移动到下一页 |
\v | 垂直制表符 | 在输出中插入一个垂直制表符,用于垂直对齐文本 |
\ooo | 八进制编码字符 | 表示一个八进制编码的字符 |
\xhh | 十六进制编码字符 | 表示一个十六进制编码的字符 |
\uhhhh | Unicode 编码字符 | 表示一个 Unicode 编码的字符(16 位) |
\Uhhhhhhhh | Unicode 编码字符 | 表示一个 Unicode 编码的字符(32 位) |
示例
package main
import "fmt"
func main() {
// 演示转义字符的用法
// \n 换行
fmt.Println("aaa\nbbb")
// \b 退格
fmt.Println("aaa\bbbb")
// \r 回车:光标回到本行的开头,后续输入会替换原有的字符
fmt.Println("aaaaa\rbbb")
// \t 制表符:水平制表符,用于对齐文本
fmt.Println("aaaaaaaaaaaaa")
fmt.Println("aaaaa\tbbbbb")
fmt.Println("aaaaaaaa\tbbbbb")
// \" 双引号:表示一个双引号字符
fmt.Println("\"Golang\"")
}
布尔类型
- 布尔类型也叫bool类型,bool类型数据只允许取值true和false
- 布尔类型占1个字节。
- 布尔类型适于逻辑运算,一般用于程序流程控制
package main
import "fmt"
func main() {
// 测试布尔类型的数值
var flag1 bool = true
fmt.Println(flag1) // 输出: true
var flag2 bool = false
fmt.Println(flag2) // 输出: false
var flag3 bool = 5 < 9
fmt.Println(flag3) // 输出: true
}
字符串类型
字符串就是一串固定长度的字符连接起来的字符序列。
字符串示例
package main
import "fmt"
func main() {
// 1. 定义一个字符串
var s1 string = "全面拥抱Golang"
fmt.Println(s1)
// 2. 字符串是不可变的:指的是字符串一旦定义好,其中的字符的值不能改变
var s2 string = "abc"
// s2 = "def"
// s2[0] = 't'
fmt.Println(s2)
// 3. 字符串的表示形式
// (1) 如果字符串中没有特殊字符,字符串的表示形式用双引号
// var s3 string = "asdfasdfasdf"
// (2) 如果字符串中有特殊字符,字符串的表示形式用反引号 ``
var s4 string = `
package main
import "fmt"
func main(){
//测试布尔类型的数值:
var flag01 bool = true
fmt.Println(flag01)
var flag02 bool = false
fmt.Println(flag02)
var flag03 bool = 5 < 9
fmt.Println(flag03)
}`
fmt.Println(s4)
// 4. 字符串的拼接效果
var s5 string = "abc" + "def"
s5 += "hijk"
fmt.Println(s5)
// 当一个字符串过长的时候:注意:+ 保留在上一行的最后
var s6 string = "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def"
fmt.Println(s6)
}
基本数据类型的默认值
在Golang中数据类型都有一个默认值,当程序员没有赋值时,就会保留默认值(默认值又叫零值)。
以下是一个表格,展示了 Go 语言中各种数据类型的默认值:
数据类型 | 默认值 | 说明 |
---|---|---|
int | 0 | 整数类型默认值 |
uint | 0 | 无符号整数类型默认值 |
float32 | 0.0 | 单精度浮点数默认值 |
float64 | 0.0 | 双精度浮点数默认值 |
bool | false | 布尔类型默认值 |
string | "" | 空字符串默认值 |
array | 元素的默认值 | 数组元素类型的默认值 |
slice | nil | 切片类型默认值 |
map | nil | 映射类型默认值 |
pointer | nil | 指针类型默认值 |
function | nil | 函数类型默认值 |
channel | nil | 通道类型默认值 |
struct | 结构体字段的默认值 | 结构体中各字段类型的默认值 |
这个表格包含了 Go 语言中各种数据类型的默认值。当声明一个变量而不指定初始值时,变量会被赋予其数据类型的默认值。例如,整数类型的默认值是 0,布尔类型的默认值是 false,字符串类型的默认值是空字符串("")。对于复合数据类型(如数组、切片、映射、结构体等),它们的默认值取决于其元素或字段的数据类型。
基本数据类型之间的转换
Go在不同类型的变量之间赋值时需要显式转换,并且只有显式转换(强制转换)。
语法:
表达式T(v)将值v转换为类型T
- T : 就是数据类型
- v : 就是需要转换的变量
类型转换示例
package main
import "fmt"
func main() {
// 类型转换示例
// 声明一个 int 类型变量
var num1 int = 100
fmt.Println(num1)
// 将 int 类型转换为 float32 类型
var num2 float32 = float32(num1)
fmt.Println(num2)
// 注意:num1 的类型仍然是 int,只是将 num1 的值 100 转换为了 float32 类型
fmt.Printf("%T\n", num1) // 输出: int
// 将 int64 类型转换为 int8 类型时,可能会发生数据溢出
var num3 int64 = 888888
var num4 int8 = int8(num3)
fmt.Println(num4) // 输出: 56
// 将 int32 类型转换为 int64 类型,并进行数值运算
var num5 int32 = 12
var num6 int64 = int64(num5) + 30
fmt.Println(num5)
fmt.Println(num6)
// 将 int64 类型转换为 int8 类型时,可能会发生数据溢出
var num7 int64 = 12
var num8 int8 = int8(num7) + 127
// 编译通过,但结果可能会溢出
fmt.Println(num8) // 输出: -117
// 将 int64 类型转换为 int8 类型时,可能会发生数据溢出
// var num9 int8 = int8(num7) + 128 // 编译不会通过,因为 128 超出了 int8 的取值范围
}
基本数据类型转为string
在程序开发中,我们经常需要将基本数据类型转成string类型。或者将string类型转成基本数据类型。
方式1:mt.Sprintf(“%参数”,表达式) 推荐方式
package main
import (
"fmt"
)
func main() {
// 将 int 类型转换为 string 类型
num1 := 42
str1 := fmt.Sprintf("%d", num1)
fmt.Printf("str1: %s, type: %T\n", str1, str1)
// 将 float64 类型转换为 string 类型
num2 := 3.14159
str2 := fmt.Sprintf("%.2f", num2)
fmt.Printf("str2: %s, type: %T\n", str2, str2)
// 将 bool 类型转换为 string 类型
flag := true
str3 := fmt.Sprintf("%t", flag)
fmt.Printf("str3: %s, type: %T\n", str3, str3)
}
按使用频率排序的 fmt.Printf()
占位符:
占位符 | 说明 | 示例 |
---|---|---|
%v | 默认格式输出,根据变量的类型自动选择输出格式 | fmt.Printf("%v", x) |
%s | 输出字符串 | fmt.Printf("%s", x) |
%d | 输出十进制整数 | fmt.Printf("%d", x) |
%f | 输出浮点数,不使用科学计数法 | fmt.Printf("%f", x) |
%T | 输出变量的类型 | fmt.Printf("%T", x) |
%t | 输出布尔值 | fmt.Printf("%t", x) |
%x | 输出十六进制整数,使用小写字母 | fmt.Printf("%x", x) |
%X | 输出十六进制整数,使用大写字母 | fmt.Printf("%X", x) |
%b | 输出整数的二进制表示 | fmt.Printf("%b", x) |
%e | 输出科学计数法表示的浮点数,使用小写字母 e |
fmt.Printf("%e", x) |
%E | 输出科学计数法表示的浮点数,使用大写字母 E |
fmt.Printf("%E", x) |
%g | 输出浮点数,根据数值大小自动选择使用 %f 或 %e 格式 | fmt.Printf("%g", x) |
%G | 输出浮点数,根据数值大小自动选择使用 %f 或 %E 格式 | fmt.Printf("%G", x) |
%p | 输出指针的十六进制表示 | fmt.Printf("%p", x) |
%c | 输出整数对应的 Unicode 字符 | fmt.Printf("%c", x) |
%o | 输出八进制整数 | fmt.Printf("%o", x) |
%q | 输出带引号的字符串或字符,对于字符串,输出双引号;对于字符,输出单引号 | fmt.Printf("%q", x) |
%U | 输出 Unicode 码点表示的字符串 | fmt.Printf("%U", x) |
%+v | 输出结构体时,包含字段名 | fmt.Printf("%+v", x) |
%#v | 输出 Go 语言语法格式的值 | fmt.Printf("%#v", x) |
%% | 输出一个百分号(% ) |
fmt.Printf("%%") |
%n | 输出已写入的字节数(n 为 int 类型的指针) | fmt.Printf("%n", &x) |
方式2:使用strconv包的函数
package main
import (
"fmt"
"strconv"
)
func main() {
// 将 int 类型转换为 string 类型
num1 := 42
str1 := strconv.Itoa(num1)
fmt.Printf("str1: %s, type: %T\n", str1, str1)
// 将 float64 类型转换为 string 类型
num2 := 3.14159
str2 := strconv.FormatFloat(num2, 'f', 2, 64)
fmt.Printf("str2: %s, type: %T\n", str2, str2)
// 将 bool 类型转换为 string 类型
flag := true
str3 := strconv.FormatBool(flag)
fmt.Printf("str3: %s, type: %T\n", str3, str3)
// 将 int64 类型转换为 string 类型
num3 := int64(123456789)
str4 := strconv.FormatInt(num3, 10)
fmt.Printf("str4: %s, type: %T\n", str4, str4)
// 将 uint64 类型转换为 string 类型
num4 := uint64(987654321)
str5 := strconv.FormatUint(num4, 10)
fmt.Printf("str5: %s, type: %T\n", str5, str5)
}
两者差异
fmt.Sprintf()
和 strconv
包中的函数之间的主要区别在于性能和灵活性:
- 性能:
strconv
包中的函数通常比fmt.Sprintf()
更快,因为它们专门针对特定的数据类型进行了优化。fmt.Sprintf()
是一个通用的格式化字符串函数,因此它需要处理更多的类型和格式选项,这可能会导致性能略低于strconv
包中的函数。 - 灵活性:
fmt.Sprintf()
提供了更多的格式选项和控制,可以轻松地处理多种数据类型和格式。而strconv
包中的函数是专门针对特定数据类型的,因此在某些情况下可能不如fmt.Sprintf()
灵活。
根据实际需求和性能要求,可以选择使用 fmt.Sprintf()
或 strconv
包中的函数进行数据类型转换。在对性能要求不高的情况下,使用 fmt.Sprintf()
可能更方便和简单。在对性能要求较高的情况下,可以考虑使用 strconv
包中的函数。
string转为基本数据类型
package main
import (
"fmt"
"strconv"
)
func main() {
// 将 string 类型转换为 int 类型
str1 := "42"
num1, err1 := strconv.Atoi(str1)
if err1 != nil {
fmt.Println("Error:", err1)
} else {
fmt.Printf("num1: %d, type: %T\n", num1, num1)
}
// 将 string 类型转换为 float64 类型
str2 := "3.14159"
num2, err2 := strconv.ParseFloat(str2, 64)
if err2 != nil {
fmt.Println("Error:", err2)
} else {
fmt.Printf("num2: %f, type: %T\n", num2, num2)
}
// 将 string 类型转换为 bool 类型
str3 := "true"
flag, err3 := strconv.ParseBool(str3)
if err3 != nil {
fmt.Println("Error:", err3)
} else {
fmt.Printf("flag: %t, type: %T\n", flag, flag)
}
// 将 string 类型转换为 int64 类型
str4 := "123456789"
num3, err4 := strconv.ParseInt(str4, 10, 64)
if err4 != nil {
fmt.Println("Error:", err4)
} else {
fmt.Printf("num3: %d, type: %T\n", num3, num3)
}
// 将 string 类型转换为 uint64 类型
str5 := "987654321"
num4, err5 := strconv.ParseUint(str5, 10, 64)
if err5 != nil {
fmt.Println("Error:", err5)
} else {
fmt.Printf("num4: %d, type: %T\n", num4, num4)
}
}
指针
&
取内存地址*
根据地址取值
package main
import "fmt"
func main() {
// 声明一个整数变量 num
num := 42
fmt.Println("num:", num)
// 声明一个指针变量 ptr
var ptr *int
// 将 num 的地址赋值给 ptr
ptr = &num
fmt.Println("ptr points to:", *ptr)
// 通过 ptr 访问 num 的值
fmt.Println("Value of num through ptr:", *ptr)
// 通过 ptr 修改 num 的值
*ptr = 100
fmt.Println("New value of num:", num)
}
指针细节
- 指针变量的地址不可以不匹配:不能指向不同数据类型
- 基本数据类型(又叫值类型),都有对应的指针类型,形式为*数据类型,比如int的对应的指针就是
*int
, float32对应的指针类型就是*float32
。依次类推。
附录
关键字和预定义标识符
关键字是 Go 语言中具有特殊含义的单词,用于控制语言结构。预定义标识符是 Go 语言中预先声明的常量、类型、函数等。在命名变量、函数或类型时,应避免使用这些关键字和预定义标识符。
关键字就是程序发明者规定的有特殊含义的单词,又叫保留字。
关键字:
go语言中一共有25个关键字。
关键字 | 说明 |
---|---|
break | 跳出循环或 switch 语句 |
default | switch 语句的默认分支 |
func | 声明函数或方法 |
interface | 声明接口类型 |
select | 用于从多个通道中接收数据 |
case | switch 语句的每个分支 |
defer | 延迟执行函数,直到包含该 defer 语句的函数执行完毕 |
go | 以并发方式运行函数 |
map | 声明映射类型 |
struct | 声明结构体类型 |
chan | 声明通道类型 |
else | if 语句的其他分支 |
goto | 无条件跳转到指定标签位置 |
package | 声明包名 |
switch | 多分支选择语句 |
const | 声明常量 |
fallthrough | 使 switch 语句继续执行下一个 case 分支,而不是跳出 switch 语句 |
if | 条件判断语句 |
range | 用于遍历数组、切片、字符串或映射的元素 |
type | 声明自定义类型 |
continue | 跳过当前循环的剩余部分,进入下一次循环 |
for | 循环语句 |
import | 导入外部包 |
return | 从函数返回 |
var | 声明变量 |
Go 语言的 36 个预定义标识符
基本数据类型:
预定义标识符 | 说明 |
---|---|
bool | 布尔类型 |
byte | 字节类型,等同于 uint8 |
complex64 | 64 位复数类型 |
complex128 | 128 位复数类型 |
error | 错误接口 |
float32 | 单精度浮点数类型 |
float64 | 双精度浮点数类型 |
int | 有符号整数类型 |
int8 | 8 位有符号整数类型 |
int16 | 16 位有符号整数类型 |
int32 | 32 位有符号整数类型 |
int64 | 64 位有符号整数类型 |
rune | 字符类型,等同于 int32 |
string | 字符串类型 |
uint | 无符号整数类型 |
uint8 | 8 位无符号整数类型 |
uint16 | 16 位无符号整数类型 |
uint32 | 32 位无符号整数类型 |
uint64 | 64 位无符号整数类型 |
uintptr | 无符号整数指针类型 |
系统内置函数:
预定义标识符 | 说明 |
---|---|
make | 分配内存并初始化切片、映射或通道 |
new | 分配内存并初始化变量 |
panic | 引发运行时恐慌 |
recover | 从运行时恐慌中恢复 |
打印参数列表 | |
println | 打印参数列表并换行 |
预定义常量:
预定义标识符 | 说明 |
---|---|
true | 布尔类型的真值 |
false | 布尔类型的假值 |
iota | 用于常量计数器的特殊常量 |
nil | 零值指针 |
这些表格包含了 Go 语言的预定义标识符,包括基本数据类型、系统内置函数和预定义常量。在命名变量、函数或类型时,应避免使用这些预定义标识符。
扩展:进制和进制转换
在 Go 语言中,可以使用不同的进制表示整数,如二进制、八进制、十进制和十六进制。以下是各种进制表示的整数的示例:
- 二进制:以
0b
或0B
开头,后跟二进制数字(0
和1
)。例如:0b1010
或0B1010
表示十进制数 10。 - 八进制:以
0
开头,后跟八进制数字(0
到7
)。例如:012
表示十进制数 10。 - 十进制:直接写十进制数字(
0
到9
)。例如:10
表示十进制数 10。 - 十六进制:以
0x
或0X
开头,后跟十六进制数字(0
到9
,A
到F
或a
到f
)。例如:0xA
或0Xa
表示十进制数 10。
进制转换
在 Go 语言中,可以使用 fmt.Printf()
或 strconv
包中的函数进行进制转换。以下是一些示例:
package main
import (
"fmt"
"strconv"
)
func main() {
num := 42
// 十进制转二进制
binStr := strconv.FormatInt(int64(num), 2)
fmt.Printf("Decimal %d to binary: %s\n", num, binStr)
// 十进制转八进制
octStr := strconv.FormatInt(int64(num), 8)
fmt.Printf("Decimal %d to octal: %s\n", num, octStr)
// 十进制转十六进制
hexStr := strconv.FormatInt(int64(num), 16)
fmt.Printf("Decimal %d to hexadecimal: %s\n", num, hexStr)
// 二进制转十进制
binNum, _ := strconv.ParseInt("101010", 2, 0)
fmt.Printf("Binary 101010 to decimal: %d\n", binNum)
// 八进制转十进制
octNum, _ := strconv.ParseInt("52", 8, 0)
fmt.Printf("Octal 52 to decimal: %d\n", octNum)
// 十六进制转十进制
hexNum, _ := strconv.ParseInt("2A", 16, 0)
fmt.Printf("Hexadecimal 2A to decimal: %d\n", hexNum)
}
在这个示例中,我们使用了 strconv.FormatInt()
和 strconv.ParseInt()
函数进行进制转换。这些函数可以根据需要将整数在不同进制之间进行转换。注意,strconv.ParseInt()
函数在转换过程中可能会发生错误(例如,无效的输入或溢出),因此需要检查返回的错误。