基本数据类型
数值型
整数不同类型的取值范围
有符号:int,int8(8位,byte是int8的别名),int16,int32(rune是int32的别名,表示一个unicode码点),int64
无符号:uint,uint8,uint16,uint32,uint64
有符号
整数类型,就是用于存放整数值的,比如0,-1,234等等
说明:
例如:int8,表示此数据类型占用空间为8位(1字节),
第一位,符号位,0表示无符号,1表示有符号,
剩余的7位表示数值,所以表示范围为2的-7到2的7次方-1(减得那个1是0),对于0表示时会有正0和-0,其实都是0所以负数部分就多了1个可以表示的数值
无符号
无符号的整数,特点是没有符号,所以第一位也可以表示数值本身,范围比有符号的要大一些,从0开始
其他的数值类型
整数型的使用细节
- Golang各整数类型分为:有符号和无符号,int uint的大小和操作系统有关
- golang的整形默认声明为int型
- 如何在程序查看某个变量的字节大小和数据类型
fmt.Printf("n1的类型为:%T",n1),查看变量的类型(%T)
fmt.Printf("n1占用的字节数是:%d",n1,unsafe.Sizeof(n1)),查看变量的所占用的字节数
- golang程序中整型变量在使用时,遵守保小不保打的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型,如年龄,不会为负数,最大为130+ 所以选用uint8(byte)最为合适
- bit:计算机中的最小存储单位,byte:计算机中基本存储单元,1byte = 8bit
浮点类型
存放小数,比如1.2,0.32
float32,float64
说明:
- 浮点数在机器中存放的方式:浮点数=符号位+指数为+尾数位
3.56
11110000111.11111111111111111000
科学计数法
7.809..*10的6次方
2. 尾数部分可能丢失,造成精度损失.(-123.0000901)
float64的精度比float32的精度更准确,如果要保存一个精度高的数应该选用float64
3. 浮点型的存储分为三部分:符号位+指数位+尾数位,在存储过程中,精度会有丢失
使用浮点型注意事项
- golang浮点类型有固定的范围和字段长度,不受具体OS(操作系统)的影响
- goalng的浮点型默认声明为float64类型
- 浮点型常量有两种方式表示
1). 十进制数形式:如:5.12 0.512可以用.512表示(必须有小数点)
2). 科学计数法形式:如:5.1234e2 = 5.12*10的2次方 5.12E-2=5.12/10的2次方
4.通常情况下应该使用float64,因为它比float32更准确
字符类型(char)
Go语言中没有专门的字符型,如果要存储单个字符(字母),一般使用byte来保存
字符串就是一串固定长度的字符连接起来的字符序列. Go的字符串是由单个字节链接起来的,也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的
说明:当输出byte值时,就是输出了对应的ASCII码值
如果希望输出对应的字符:用格式化输出
fmt.Printf("c1=%c c2=%c",c1,c2)
如果是汉字的话,需要看值是否在byte的码值范围内
overflow溢出,处理方式
输出汉字对应的码值
说明:
1.如果保存的字符在ASICC表中,比如[0-1,a-z,A-Z],可以保存到byte中
2.如果保存的字符对应码值大于255,这时考虑用int类型保存
3.如果需要按照字符的方式输出,而不是码值,只是需要格式化输出,即fmt.Printf("%c",c1)
字符类型使用的注意事项
1.字符常量是用单引号('')引起来的单个字符,
例如:var c1 byte = 'a'
var c2 int = '中'
var c3 byte = '9'
2.Go中允许使用转义字符''来讲其后的字符转变成特殊字符型常量
例如:
var c3 char = '\n' //'\n'表示换行符
3.Go语言的字符使用UTF-8编码
4.在Go中字符的本质是一个整体,直接输出时,是该字符对应的UTF-8编码的码值
5.可以直接给某个变量赋一个数字,然后按格式化输出时%c会输出改数字对应的Unicode字符
6.字符类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码
字符类型的本质
1.字符型存储到计算机中,需要将字符对应的码值(整数)找到
存储:找到汉字对应的码值,转成二进制,存储
读取:二进制转成码值,通过码值到utf8对照表中找到对应的字符,读取
2.字符和码值的对应关系是通过字符编码表决定的(规定死的)
3.Go语言的编码都统一成了utf-8,非常的方便,很统一,再也没有编码乱码的问题
布尔型
布尔类型也叫bool类型,只允许取值true和false,占用1字节,通常用于逻辑运算,流程控制
字符串
官方将string归属到基本数据类型
字符串就是一串固定长度的字符连接起来的字符序列,Go的字符串是由单个字节链接起来的,Go语言的字符串的字节的字节使用UTF-8编码表示Unicode文本
package main
import "fmt"
func main() {
var address string = "背景你好"
fmt.Println(address)
}
字符串使用细节
1.Go语言的字符串的字节使用UTF-8编码表示Unicode文本,这样Golang同意使用UTG-8编码乱码问题不会再成为困扰
2.字符串一旦赋值,字符串就不能修改了,在Go中字符串是不可变的
package main
import (
"fmt"
"unsafe"
)
func main() {
var address string = "背景你好"
address[0] = "我不好" // 不可改变字符串中的某个元素
address = "我不好" // 可以重新赋值
fmt.Println(address,unsafe.Sizeof(address))
}
# cannot assign to address[0] (strings are immutable)
3.字符串的表示方法有两种
1).双引号,会识别\这种转义字符
2).反引号`,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止共计,或者输出源代码等效果
4.字符串拼接方式
package main
import (
"fmt"
)
func main() {
var address string = "背景你好"
var age string = "18"
var address_age = address + age
// address += age
// fmt.Println(address)
fmt.Println(address_age)
}
- 当字符串的长度太长是,需要使用到多行字符串,注意需要将+保留在上一行,因为编译器会自动加分号
不保留在上一行,会表示这一行代码结束了,下一行代码就会有错
package main
import (
"fmt"
)
func main() {
var address string = "背景你好" +
"今天"
// var address string = "背景你好"
// + "今天" //错误!!!
fmt.Println(address)
}
基本数据类型的默认值.
在Go中,数据类型都有一个默认值,当没有赋值时,就会保留其默认值,在Go中的默认值又叫做零值
基本数据类型的转换
Golang和java/c 不同,Go在不同类型的变量之间赋值时需要显示转换(强制转换),也就是说golang中数据类型不能自动转换
表达式为:T(v)
将值v转换为类型T
T:就是数据类型,比如int32,int64,float32等等
v:就是需要转换的变量
package main
import (
"fmt"
)
func main() {
var str_num int = 1
int_num := int32(str_num)
var float_num = 3.125
var new_float_num float32 = float32(float_num)
fmt.Println(int_num,new_float_num)
}
package main
import (
"fmt"
)
func main() {
var str_num int = 1
int_num := float64(str_num)
fmt.Println(int_num)
}
数据类型转换注意事项
1.Go中,数据类型的转换可以从表示范围小->表示范围打,表示范围打->表示范围小
2.被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!
3.在转换中,比如将int64转成int8,编译时不会报错,只是转换的结果是按溢出处理(得到一个和希望结果不一样的值)
注意
编译无法通过
如何修改代码可以正确?(go语言不支持自动转换数据类型,需要强转类型)
基础数据类型和string的转换
在程序开发中,经常需要将基本数据类型转换成string类型,或者将string类型转成基本数据类型
基本数据类型转string
方式:
1.fmt.Sprintf("%参数",表达式)
1).参数需要和表达式的数据类型相匹配
2).fmt.Sprintf()会返回转换后的字符串
package main
import (
"fmt"
)
func main() {
var str1_num int = 1000
var str2_num float64 = 154.24554
var str3_num bool = true
var str4_num byte = 'h'
var str string // 空的字符串
str = fmt.Sprintf("%d", str1_num)
str = fmt.Sprintf("%d", str2_num)
str = fmt.Sprintf("%t", str3_num)
str = fmt.Sprintf("%w", str4_num)
fmt.Printf("str1_num 转换后的 type (%T) is %q\n", str, str)
fmt.Printf("str2_num 转换后的 type (%T) is %q\n", str, str)
fmt.Printf("str3_num 转换后的 type (%T) is %q\n", str, str)
fmt.Printf("str4_num 转换后的 type (%T) is %q", str, str)
}
2.使用strconv包的函数
package main
import (
"fmt"
"strconv"
)
func main() {
var str1_num int = 1000
var str2_num float64 = 154.24554
var str3_num bool = true
var str4_num int = 123
var str4_num int64 = 456
var str string // 空的字符串
str = strconv.FormatInt(int64(str1_num),2) // int64转成二进制的字符串
fmt.Printf("str1_num(%T) 转换后为 %q\n",str,str)
str = strconv.FormatFloat(str2_num,'f',10,64) // float转成10位的float64的字符串
fmt.Printf("str1_num(%T) 转换后为 %q\n",str,str)
str = strconv.FormatBool(str3_num) // bool 转成 字符串
fmt.Printf("str1_num(%T) 转换后为 %q\n",str,str)
str = strconv.Itoa(str4_num) // int类型很方便的转换成字符串
fmt.Printf("str (%T) 转换后为%q",str,str)
str = strconv.Itoa(int(str5_num)) // int64必须转成int,才可以用这个函数
fmt.Printf("str (%T) 转换后为%q",str,str)
}
string转成基本数据类型
package main
import (
"fmt"
"strconv"
)
func main() {
var str1 string = "true"
var str_to_bool bool
str_to_bool , _ = strconv.ParseBool(str1)
fmt.Printf("str_to_bool (%T) 转换成%q\n",str_to_bool,str_to_bool)
var str2 string = "123456"
var str_to_int int64
var str_to_int2 int
str_to_int , _ = strconv.ParseInt(str2,10,64) // 只能转成int64,如果是int需要强转
str_to_int2 = int(str_to_int)
fmt.Printf("str_to_bool (%T) 转换成%v\n",str_to_int2,str_to_int2)
var str3 string = "12.1254"
var str_to_float float64
str_to_float , _ = strconv.ParseFloat(str3,64)
fmt.Printf("str_to_float (%T) 转换成%v",str_to_float,str_to_float)
}
说明: 因为返回的是int64或者float64,如果希望得到int32或float32,用int32()/float32()强转一下
注意事项
在将string类型转换成基本数据类型时,要确保string类型能够转成有效的数据,比如可以吧"123"转成一个整数,但是不能把"hello" 转成一个整数,如果这样做,Golang 直接将其转换成0,其他所有转不成功的数据类型都会置其为默认值
派生/复杂数据类型
指针(pointer)
基本介绍
1.基本数据类型,变量存的是值,也叫值类型
2.获取变量的地址,用&,比如:var num int,获取num的地址:&num
var i int = 100
fmt.Printf("i的内存地址为",&i)
3.指针类型,变量存的是一个地址,这个地址指向的空间存的才是值,比如var ptr *int=&num
package main
import "fmt"
func main() {
var i int = 100
fmt.Printf("i的内存地址为%v\n",&i)
// xx是一个指针变量,类型是*int,并且指向i的内存地址,内存地址指向的才是值
var xx *int = &i
// 指针变量也是有自己的内存地址的
fmt.Printf("xx指向的内存地址为%v\n",xx,)
fmt.Printf("xx指针变量的内存地址为",&xx)
}
4.获取指针类型所指向的值,使用:*,比如var ptr int,使用ptr获取p指向的值
package main
import "fmt"
func main() {
var i int = 100
fmt.Printf("i的内存地址为%v\n",&i)
// xx是一个指针变量,类型是*int,并且指向i的内存地址,内存地址指向的才是值
var xx *int = &i
// 指针变量也是有自己的内存地址的
fmt.Printf("xx指向的内存地址为%v\n",xx,)
fmt.Printf("xx指针变量的内存地址为%v\n",&xx)
fmt.Printf("xx指针变量指向的值为",*xx)
}
练习
题目:
1.写一个程序,获取int变量num的地址,并显示到终端
2.将num的地址赋给指针ptr,并通过ptr去修改num的值
package main
import "fmt"
func main() {
var num int = 500
fmt.Printf("i的内存地址为%v\n",&num)
var ptr *int = &num
*ptr = 500
fmt.Printf("改变后的值为num=",num)
}
指针的注意事项
1.值类型,都有对应的指针类型,形式为*数据类型,比如int的对应的指针就是int,float32 对应的指针类型就是float32,依次类推
2.值类型包括:基本数据类型int系列,float系列,bool,string,数组和结构体(struct)
值类型和引用类型
值类型和引用类型在go中都有哪些数据结构
1.值类型:基本数据类型int系列,float系列,bool,string,数组和结构体struct
2.引用类型:指针,slice切片,map,管道channel,接口(interface)等都是引用类型
区别
1.值类型,变量直接存储值,内存通常在栈中分配
2.引用类型,变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配.当没有任何变量引用这个地址时,该地址对应的数据空间就变成为一个垃圾有GC来回收