Go数据类型
-
C语言的数据类型
-
GO语言数据类型
-
GO数据类型占用的内存空间
package main
import (
"fmt"
"unsafe"
)
func main() {
// 有符号的整型
fmt.Println("int size = ", unsafe.Sizeof(int(0))) // 8
fmt.Println("int8 size = ", unsafe.Sizeof(int8(0))) // 1
fmt.Println("int16 size = ", unsafe.Sizeof(int16(0))) // 2
fmt.Println("int32 size = ", unsafe.Sizeof(int32(0))) // 4
fmt.Println("int64 size = ", unsafe.Sizeof(int64(0))) // 8
// 结论: int会根据系统自动调整,如果系统是64的,那么int就会变成int64,
// 如果系统是32的, 那么int 就会变成32位
// 无符号的整型
fmt.Println("uint size = ", unsafe.Sizeof(uint(0))) // 8
fmt.Println("uint8 size = ", unsafe.Sizeof(uint8(0))) // 1
fmt.Println("uint16 size = ", unsafe.Sizeof(uint16(0))) // 2
fmt.Println("uint32 size = ", unsafe.Sizeof(uint32(0))) // 4
fmt.Println("uint64 size = ", unsafe.Sizeof(uint64(0))) // 8
// 字符类型
fmt.Println("byte size = ", unsafe.Sizeof(byte(0))) // 1
fmt.Println("rune size = ", unsafe.Sizeof(rune(0))) // 4
fmt.Println("中文字符 = ", unsafe.Sizeof('好')) // 4
// 浮点类型
fmt.Println("float32 size = ", unsafe.Sizeof(float32(0))) // 4
fmt.Println("float64 size = ", unsafe.Sizeof(float64(0))) // 8
// 布尔类型
fmt.Println("true size = ", unsafe.Sizeof(true)) // 1
fmt.Println("false size = ", unsafe.Sizeof(false)) // 1
}
- 注意点:
- 在GO语言中我们可以通过Sizeof来计算数据类型占用的内存大小
- 使用Sizeof函数必须导入unsafe这个包
- 通过unsafe.Sizeof()来调用这个方法
- Sizeof的首字母必须大写
- Go语言中int类型,会根据系统自动调整占用内存的字节数
- 如果是64位系统, 那么int就是int64, 占用 8个字节
- 如果是32位系统, 那么int就是int32, 占用 4个字节
GO语言变量
- 变量: 可以改变的数据称为变量
- 定义变量: 就是告诉系统需要分配多大的内存空间来存储数据
- 格式:
- 1.var 变量名称 数据类型
- 2.var 变量名称 数据类型 = 值
- 3.var 变量名称 = 值
- 4.变量名称 := 值
package main import ( "fmt" ) func main() { // 先定义后初始化 var num int num = 666 fmt.Printf("num = %d\n", num) // 666 // 定义的同时初始化 var num1 int = 123 fmt.Println("num1 = ", num1) // 定义的同时初始化, 并省略数据类型 var num2 = 234 fmt.Println("num2 = ", num2) // fmt.Println("int sizeof = ", unsafe.Sizeof(num2)) // 定义的同时初始化, 并省略数据类型和var // := 做了两件事 // 1. 先定义一个变量 // 2. 给定义的变量赋值 num3 := 100 fmt.Println("num3 = ", num3) // num4 int:= 23 // := 定义变量的同时不能添加数据类型 var num5 := 555 // := 定义变量的同时不能添加 var fmt.Println("num4 = ", num5) }
连续定义多个变量
- 格式:
- 1.可以通过逗号来定义多个变量
// 先定义变后初始化 var a , b , c int a = 1 b = 2 c = 3 // 定义变量的同时初始化 var a , b, c int = 1, 2, 3
- 2.可以使用变量组来同时定义多个变量
// 先定义变量后初始化 var( a int b int c int ) a = 1 b = 2 c = 3 // 定义变量同时初始化 var ( a int = 1 b int = 2 c int = 3 ) // 注意点: 变量组中不能使用 := 来定义变量 // var ( // a := 1 // b := 2 // )
定义变量的注意点:
- 定义变量的时候, 如果省略数据类型那么系统会自动根据数值推断出变量的数据类型
- 使用 := 定义变量的时候, 那么不能写var 也不能写数据类型
- 使用 := 定义变量的时候, 只能定义局部变量不能定义全局变量
- 使用 := 定义变量的时候, 变量组中不能使用 := 的格式
- 使用 := 定义多个变量的时候, 变量如果已经定义过了那么将退化成赋值操作
// 定义一个变量
var num int = 234
// 对于num已经定义过了, 那么将退化成赋值操作
num , value := 666, 777
fmt.Println("num = ", num, "value = ", value)
- 重复定义变量编译报错
package main
import "fmt"
func main() {
num := 234
num := 666
fmt.Println("num = ", num)
}
全局变量和局部变量
- 局部变量:
- 含义: 定义在函数内部的变量,以及函数的形参就称为局部变量
- 作用域: 从定义的哪一行开始到遇到}和return,到代码块结束就释放
- 生命周期: 从程序运行到哪一行才分配存储空间, 离开作用域就释放空间
- 全局变量:
- 含义: 定义在函数外部的变量称为全局变量
- 作用域: 从定义哪一行开始到文件的结尾
- 生命周期: 程序一启动就分配存储空间, 知道程序结束
- 注意点:
- GO语言中不管是定义局部变量还是全局变量都不能出现同名的变量
- GO语言中,如果定义一个局部变量, 但是没用使用这个变量, 编译报错
- GO语言中,如果定义一个全局变量, 但是没用使用这个变量, 编译不会报错
数值类型和字符串类型之间的转换
- GO语言中只有显示转换, 没有隐式转换
- 数据类型一般用于除了字符串和布尔类型以外的其他基本类型的转换
package main
func main() {
// go语言中只有显示转换没有隐式转换
// 格式:数据类型(被转换的数据)
num int = 3.14 // 报错
fmt.Println("num = ", num)
不能对一个常量进行类型的强行转换
var num1 int = int(3.14)
fmt.Println("num1 = ", num1)
// 正确做法
// go语言中数据类型必须一模一样才能直接赋值
var num3 float64 = 3.14
var value int = int(num3)
fmt.Println("value = ", value) // 3
// 特殊情况
var ch byte = 'a'
var num4 uint8 = ch // type byte = uint8 本质
fmt.Println("num4 = ", num4) // 97
var ch1 rune = '好'
var num5 int32 = ch1
fmt.Println("num5 = ", num5) // 22909 UTF -8
// bool 类型不能转换为整型
//var flag bool = false
//var num6 int = flag
//fmt.Println("num6 = ", num6)
// 整型也可以转换成字符类型, 但是不推荐使用
//var num7 int = 97
//var str string = string(num7)
//fmt.Println("str = ", str) // a
}
- 基本数据类型转换成字符串类型
- 方法一: strconv.FormatXxx()
- 方法二: strconv.Itoa()
package main
import (
"fmt"
"strconv"
"unsafe"
)
func main() {
// 基本数据类型转换为字符串类型
// 1. strconv.FormatXxx()
// 2. strconv.Itoa()
// strconv.FormatInt()
// func FormatInt(i int64, base int) string
// 第一个参数: 需要转换的整数, 必须是int64类型的
// 第二个参数: 转换为多少进制的字符串
var num1 int = 9
var str1 string = strconv.FormatInt(int64(num1), 10)
var str2 string = strconv.FormatInt(int64(num1), 2)
fmt.Println("str1 = ", str1) // 9
fmt.Println("str2 = ", str2)// 1001
var str3 string = strconv.FormatInt(int64(3), 10)
fmt.Println("str3 = ", str3) // 3
// strconv.FormatFloat()
// func FormatFloat(f float64, fmt byte, prec, bitSize int) string
// 第一个参数: 需要转换的小数
// 第二个参数: 按照什么格式转换 'f' 小数格式, 'e' 指数格式
// 第三个参数: 保留多少位小数, 传入 -1按照原始类型的精度保留
// 第四个参数: 原始类型的标志 float32 --> 32 float64 --> 64
var num2 = 3.14
var str4 string = strconv.FormatFloat(float64(num2), 'f', -1,32)
fmt.Println("str4 = ", str4) // 3.14
fmt.Println("sizeof num2 = ", unsafe.Sizeof(num2)) // 8
// strconv.FormatBool
// func FormatBool(b bool) string
var flag bool = false
var str5 string = strconv.FormatBool(flag)
fmt.Println("str5 = ", str5) // false
// strconv.Itoa()
// func Itoa(i int) string
var num3 int = 233
//var num3 int64 = 332
var str6 string = strconv.Itoa(int(num3))
fmt.Println("str6 = ", str6) // 233
}
- 字符类型转换为基本数据类型
- 方法一: strconv.ParseXxx()
- 方法二: strconv.Atoi()
package main
import (
"fmt"
"strconv"
)
func main() {
// Go语言中字符串类型转换为基本数据类型
// strconv.ParseXxx()
// strconv.Atoi()
// strconv.ParseInt()
// func ParseInt(s string, base int, bitSize int) (i int64, err error)
// 第一个参数: 需要转换的字符串
// 第二个参数: 被转化的字符串保存的整数是多少进制的(原来的字符是多少进制的)
// 第三个参数: 期望转换为多少位的整数
// 返回值有两个
// 第一个返回值: 转后之后的数值, 是int64 类型
// 第二个返回值: 如果转换成功返回nil, 如果转换失败就不是nil
var str1 = "1010"
// num, err := strconv.ParseInt(str1, 10, 8)
num, err := strconv.ParseInt(str1, 2, 8)
if err != nil{
fmt.Println("转换失败")
}else{
fmt.Println("num = ", num) // 9
fmt.Printf("%T ", num) // int64
}
// strconv.ParseFloat()
//func ParseFloat(s string, bitSize int) (float64, error)
// 第一个参数: 需要转换的字符串
// 第二个参数: 要将字符串中的小数转换为单精度还是双精度, 单精度传入32, 双精度传入64
// 返回两个返回值
// 第一个返回值: 转换成功之后的小数, float64类型
// 第二个返回值: 转换成功返回 nil, 转换失败不为 nil
str2 := "3.123456789"
num1, err := strconv.ParseFloat(str2, 32)
if err != nil{
fmt.Println("转换失败")
}else{
fmt.Println("num1 = ", num1)
fmt.Printf("%T", num1) // float64
}
// strconv.ParseBool()
//func ParseBool(str string) (bool, error)
var str3 string = "false"
flag, err := strconv.ParseBool(str3)
fmt.Println("flag = ", flag) // false
fmt.Printf("%T\n", flag) // bool
// strconv.Atoi()
// func Atoi(s string) (int, error)
// 传入一个字符串
// 返回两个值, 第一个是转换成功后的数, 第二个返回值是 : 转换成功返回nil,
var str4 string = "99"
num2, err := strconv.Atoi(str4)
if err != nil{
fmt.Println("转换失败")
}else{
fmt.Println("num2 = ", num2)
}
}
GO语言常量
- GO语言常量分为整型常量, 实型常量, 字符常量, 字符串常量, 自定义常量
- 自定义常量
- 格式: const 常量名称 数据类型 = 值 或者 const 常量名称 = 值
package main
import "fmt"
func main() {
// 格式: const 变量名称 数据类型 = 值
const num1 int = 222
// num1 = 111 // 常量不能赋值, 否则报错
fmt.Println("num1 = ", num1)
// 给多个变量赋值
// 格式: const 变量名1 , 变量名2 数据类型 = 值1, 值2
const num2 , num3 int = 10, 20
fmt.Println("num2 = ", num2, "num3 = ", num3)
// 使用变量组给常量赋值
const (
num4 int = 33
num5 int = 44
num6 int = 55
)
fmt.Println(num4, num5, num6)
// 变量组的定义多个变量的注意点
// 如果常量没有赋值, 那么默认值就是上一行的取值
//const (
// a = 10
// b = 20
// c = 30
//)
// fmt.Println(a, b, c) // 10 20 30
//const (
// a = 10
// b = 20
// c
//)
// fmt.Println(a, b, c) // 10 20 20
const(
a , b = 10, 20
c, d
)
fmt.Println(a, b) // 10, 20
fmt.Println(c, d) // 10, 20
}
- 注意点:
- 不能给常量赋值, 会报错
- 在常量组中, 如果常量没有赋值, 那么值为上一行的值
- 枚举常量
- 格式
const (
枚举元素1 = 值
枚举元素2 = 值
)
package main
import "fmt"
func main() {
// 枚举类型的本质就是整型常量
// Go语言和C语言一样都是从0开始递增, 每行递增1
/*const(
male = iota
female = iota
yy = iota
)*/
// 等同于下面的写法
const(
male = iota
female
yy
)
// 只要有一行出现了iota, 那么后续会自动递增
fmt.Println("male = ", male) // 0
fmt.Println("female = ", female) // 1
fmt.Println("yy = ", yy) // 2
// 如果常量组中被打断了, 那么就不会继续递增了,
// 而是会按照常量的的方式处理, 不赋值就会等于上一行的值
const (
a = iota
b = 888
c
)
fmt.Println("a = ", a) // 0
fmt.Println("b = ", b) // 888
fmt.Println("c = ", c) // 888
// 如果常量组中的iota被打断了, 但是后续又恢复, 那么前面有多少行,就会递增多少
const (
num1 = iota
num2 = 111
num3 = iota
)
fmt.Println("num1 = ",num1) // 0
fmt.Println("num2 = ",num2) // 111
fmt.Println("num3 = ",num3) // 2
}
- 注意点:
- Go语言和C语言的枚举一样,利用iota标识符从0开始递增,每行增加1
- 在常量组中, iota只要上一行出现了, 那么下一行不赋值也会递增
- 但是如果常量组中, 被常量打断了, 那么就会等于上一行的值
- 常量组如果被打断,后续又恢复,那么前面有多少行就会递增多少