零值
变量声明时没有初始化会默认赋值为零值 。
零值是:
数值类型为 0
布尔类型为 false
字符串为 "" (空字符串)
基本类型的类型转换
C语言转换
先看一下,在C语言中的类型转换,
隐式转换
int a = 10;
int b = 3.0
int num = 3.14;
double res = a/b;
显示转换
int a = 10;
int b = 3.0
double res = (double)a/b;
Golang基本类型间只能进行显示转换
但是,Golang基本类型间只能进行显示转换,
转换形式如下:
Type(value)
其中value
是要转换的值(包括变量、复杂算子和函数返回值),Type
是要转换成的类型。
在类型转换时,要考虑它们之间的关系和范围,以免精度丢失或数值截断。
特别注意:
byte --> uint8 和 rune --> int32 是能够直接赋值的特殊情况(byte就是unit8的别名,rune就是int32的别名)
看一些例子:
// 输出各数值范围
fmt.Println("int8 range:", math.MinInt8, math.MaxInt8)
fmt.Println("int16 range:", math.MinInt16, math.MaxInt16)
fmt.Println("int32 range:", math.MinInt32, math.MaxInt32)
fmt.Println("int64 range:", math.MinInt64, math.MaxInt64)
// 初始化一个32位整型值
var a int32 = 1047483647
// 输出变量的十六进制形式和十进制值
fmt.Printf("int32: 0x%x %d\n", a, a)
// 将a变量数值转换为十六进制, 发生数值截断
b := int16(a)
// 输出变量的十六进制形式和十进制值
fmt.Printf("int16: 0x%x %d\n", b, b)
// 将常量保存为float32类型
var c float32 = math.Pi
// 转换为int类型, 浮点发生精度丢失
fmt.Println(int(c))
bool不能直接转换成整型
bool类型不能强制转换为整型(bool类型在底层是0和1,不能更改为整型变量)
//bool不能直接转换成int,编译器会报错
var flag bool = false
var num int = int(flag) //报错
fmt.Printf("%d\n", num)
string与基本数据类型转换
string-->基本数据类型
- strconv.ParseXxx()
- strconv.Atoi()
string-->整型
/*------strconv.ParseInt------*/
//十进制
var str string = "4"
//转换成int8,int8范围-128~127
num, err := strconv.ParseInt(str, 10, 8)
if err != nil {
fmt.Printf("转换失败\n")
} else {
fmt.Printf("%d\n", num)
fmt.Printf("%T\n", num)
}
//十进制
var str1 string = "233"
//转换成int8,int8范围-128~127
num1, err1 := strconv.ParseInt(str1, 10, 8)
//233超过8位的长度,转换失败
if err1 != nil {
fmt.Printf("转换失败\n")
} else {
fmt.Printf("%d\n", num1)
fmt.Printf("%T\n", num1)
}
//二进制
var str2 string = "1001"
//转换成int32
num2, err2 := strconv.ParseInt(str2, 2, 32)
if err2 != nil {
fmt.Printf("转换失败\n")
} else {
fmt.Printf("%d\n", num2)
fmt.Printf("%T\n", num2)
}
/*------strconv.Atoi------*/
//10进制
var str3 string = "9" //会转换成功
//var str string = "9a" //会转换失败
num3, err3 := strconv.Atoi(str3)
if err3 != nil {
fmt.Printf("转换失败\n")
} else {
fmt.Printf("%d\n", num3)
fmt.Printf("%T\n", num3)
}
string-->浮点型
var str string = "3.1234567890123456789"
num, err := strconv.ParseFloat(str, 32)
if err != nil {
fmt.Printf("转换失败\n")
} else {
fmt.Println(num)
fmt.Printf("%T\n", num)
}
string-->布尔型
//str的值可以是1、t、T、TRUE、true、True,
//也可以是0、f、F、FALSE、false、False
var str string = "F"
//直接传入字符串
flag, err := strconv.ParseBool(str)
if err != nil {
fmt.Printf("转换失败\n")
} else {
// 注意点: 在Go语言中%t输出布尔类型
fmt.Printf("%t\n", flag) //false
fmt.Printf("%T\n", flag) //bool
}
基本数据类型-->string
- strconv.FormatXxx()
- strconv.iota()
整型-->string
/*------strconv.FormatInt------*/
var num int = 724
//转换为10进制格式
str := strconv.FormatInt(int64(num), 10)
fmt.Printf("十进制:%s\n", str) //输出:724
//转换为2进制格式
str2 := strconv.FormatInt(int64(num), 2)
fmt.Printf("二进制:%s\n", str2) //输出:1011010100
//转换为16进制格式
str16 := strconv.FormatInt(int64(num), 16)
fmt.Printf("十六进制:%s\n", str16) //输出:2d4
/*------strconv.Itoa------*/
var num4 int32 = 724
var str7 string = strconv.Itoa(int(num4))
fmt.Printf("十进制:%s\n", str7) //输出:724
浮点型-->string
var num2 float32 = 3.1234567890123456789
var str3 string = strconv.FormatFloat(float64(num2), 'f', -1, 32) // "3.1234567"
var str4 string = strconv.FormatFloat(float64(num2), 'f', -1, 64) // "3.123456789012345"
var str5 string = strconv.FormatFloat(float64(num2), 'f', 2, 32) // "3.12"
fmt.Printf("%s\n%s\n%s\n", str3, str4, str5)
bool-->string
var flag bool = false
var str6 string = strconv.FormatBool(flag)
fmt.Printf("%s\n", str6) //false
time转换
注意:time不是基本类型,但是为了方便整理也放于此处。
//获取当前时间戳,纳秒
nanoSeconds := time.Now().UnixNano()
fmt.Printf("当前纳秒时间戳:%d\n", nanoSeconds)
fmt.Printf("%T\n", nanoSeconds)
//纳秒转毫秒
fmt.Println(nanoSeconds / 1e6)
//纳秒转秒
fmt.Println(nanoSeconds / 1e9)
//获取当前时间戳,秒
seconds := time.Now().Unix()
fmt.Printf("当前秒时间戳:%d\n", seconds)
fmt.Printf("%T\n", seconds)
//将纳秒时间戳转换成时间
t := time.Unix(0, 1573541938000*1e6) //将纳秒转换为 time 类型
fmt.Printf("时间戳转换成时间格式:%s\n", t.String())
//时间格式化成string
formatStr := time.Now().Format("2006-01-02 15:04:05.000")
fmt.Printf("时间格式化成string:%s\n", formatStr)
//将年月日转换成时间
yearTime := time.Date(2014, 1, 7, 5, 50, 4, 123*1e6, time.Local)
yearUnix := yearTime.UnixNano()
fmt.Printf("年月日转换成时间秒时间戳:%d\n", yearUnix)
yearFormat := yearTime.Format("2006-01-02 15:04:05.000")
fmt.Printf("年月日转换成时间:%s\n", yearFormat)
interface{}类型转换和类型断言
- 类型转换在编译期完成,包括强制转换(类型间、接口向类型、类型向接口转换)和隐式转换(类型向接口转换)
- 类型断言在运行时确定,包括安全类型断言和非安全类型断言
Go语言要求不同类型之间必须做显式的类型转换。但似乎涉及到接口类型时,就会有所不同。
类型断言
//animal 动物
type animal interface {
//run 跑
run()
}
//duck 鸭子
type duck struct {
//name 名称
name string
//legNum 腿的数量
legNum int
}
func newDuck() duck {
return duck{
name: "duck",
legNum: 2,
}
}
func (d duck) run() {
fmt.Printf("在%d,%s跑步用%d条腿\n", time.Now().Unix(), d.name, d.legNum)
}
//cat 猫
type cat struct {
//name 名称
name string
//legNum 腿的数量
legNum int
}
func newCat() cat {
return cat{
name: "cat",
legNum: 4,
}
}
func (c cat) run() {
fmt.Printf("在%d,%s跑步用%d条腿\n", time.Now().Unix(), c.name, c.legNum)
}
func runWithRecover(a animal) {
defer func() {
fmt.Println("end")
if err := recover(); err != nil {
fmt.Printf("received panic ,the error is %s\n", err) // 这里的err其实就是panic传入的内容
}
}()
i1 := a.(cat)
i1.run()
}
//类型断言的方式
//typeAssert 类型断言的方式
func typeAssert() {
//第一种
var d animal
d = newDuck()
//不安全的类型断言,如果系统检测到不匹配,会在运行时调用内置的panic,抛出异常
i := d.(duck)
i.run()
//由于不安全断言会抛panic
runWithRecover(d)
//安全的类型断言。 其中ok为一个bool值, 表征类型转换是否成功; s为返回的int变量,如果失败返回该类型的零值
if inst, ok := d.(duck); ok {
inst.run()
}
if inst, ok := d.(cat); ok {
inst.run()
} else {
fmt.Printf("assert error,the error is %t\n", ok)
}
//第二种,type是关键字 结合switch case使用
switch inst := d.(type) {
case duck:
inst.run()
case cat:
inst.run()
default:
fmt.Println("unknow")
}
}