前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Golang】类型转换归纳总结

【Golang】类型转换归纳总结

作者头像
DDGarfield
发布2022-06-23 19:23:10
2K0
发布2022-06-23 19:23:10
举报
文章被收录于专栏:加菲的博客

实际编码中,经常会出现类型转换的情况。

1.C#中的类型转换

C#中有两种类型转换:隐式类型转换显示类型转换(也作强制转换),其中隐式转换主要是在整型、浮点型之间的转换,将存储范围小的数据类型直接转换成存储范围大的数据类型,也就是小转大

代码语言:javascript
复制
int a = 100;
double d = a;  //将int类型转换为double类型
float f = 3.14f;
d = f;    //将float类型转换为double类型

反之

代码语言:javascript
复制
int r ;
double rd=5.0;
r = rd;
代码语言:javascript
复制
Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)	

不能隐式转换doubleint:因为进行转换可能会导致信息丢失,则编译器会要求执行显式转换,显式转换也称为强制转换

代码语言:javascript
复制
int r ;
double rd=5.0;
r = (int)rd;

形为 (T)E 的强制转换表达式将表达式 E 的结果显式转换为类型 T

  • 如果不存在从类型 E 到类型 T 的显式转换,则发生编译时错误。
  • 在运行时,显式转换可能不会成功,强制转换表达式可能会引发异常。

有关支持的显式数值转换的完整列表,请参阅?内置数值转换一文的?显式数值转换部分。

对于引用类型,从基类型转换为派生类型,则必须进行显式强制转换

代码语言:javascript
复制
// 创建派生类
Giraffe g = new Giraffe();

// 隐式转换为基类是安全的
Animal a = g;

// 需要显式转换才能强制把基类转换回派生类型
Giraffe g2 = (Giraffe)a; //如果a不是Giraffe,编译能通过,但在运行时会抛出异常

另外一种特殊的类型转换是?装箱和拆箱,这里就不做介绍了。

2.Go语言中的类型转换

Go语言没有隐式转换,只有显式转换,说白了,任何一种类型转换,都需要开发者进行手动操作。

简单转换

何谓简单转换?就是转换数据类型的方式很简单。

代码语言:javascript
复制
func main() {
 a := 10
 b := float32(a)

 c := 50.5
 d := int32(c)
 e := int64(c)
 fmt.Printf("%v %T\n", a, a)
 fmt.Printf("%v %T\n", b, b)
 fmt.Printf("%v %T\n", c, c)
 fmt.Printf("%v %T\n", d, d)
 fmt.Printf("%v %T\n", e, e)
}
代码语言:javascript
复制
输出
10 int
10 float32
50.5 float64
50 int32
50 int64

注意事项

  • 不是所有数据类型都能转换的,例如string类型转换为int肯定会失败,编译就会报错cannot convert xxx (type string) to type int64
  • 低精度转换为高精度时是安全的,高精度的值转换为低精度时会丢失精度。上面的变量d与e就是这种情况;
  • 要跨大类型转换,例如string与int的互转,可以使用strconv包提供的函数

3.strconv包

这一节就归纳一些在实际开发中,strconv包中经常用到的函数:

3.1 Itoa()

Itoa()函数用于将int类型数据转换为对应的字符串表示,具体的函数签名如下。

代码语言:javascript
复制
func Itoa(i int) string

实际开发中,组合生成redis的key,key值为int类型的id

代码语言:javascript
复制
func main() {
    var userid int
    KeyPostVotedZSetPF := "post:voted:"
    userid = 41654
    key := KeyPostVotedZSetPF + strconv.Itoa(userid)
    println(key)
}
代码语言:javascript
复制
输出
post:voted:41654

3.2 FormatInt()

可以看到Itoa()接收的是int类型的参数,但是我们如果是通过雪花算法生成的用户id,是int64,那Itoa显然不能使用,FormatInt() 函数实现了将int64数据格式化为string,具体的函数签名如下:

代码语言:javascript
复制
func FormatInt(i int64, base int) string
代码语言:javascript
复制
func main() { 
    var userid int64
    KeyPostVotedZSetPF := "post:voted:"
    userid = 41654489498
    key := KeyPostVotedZSetPF + strconv.FormatInt(userid, 10)
    println(key)
}
代码语言:javascript
复制
输出
post:voted:41654489498
Format系列函数

Format其实是有一系列函数,用于实现了将给定类型数据格式化为string类型数据的功能。

FormatBool()
代码语言:javascript
复制
func FormatBool(b bool) string
FormatInt()
代码语言:javascript
复制
func FormatInt(i int64, base int) string
FormatUint()
代码语言:javascript
复制
func FormatUint(i uint64, base int) string

是FormatInt的无符号整型版本。

FormatFloat()
代码语言:javascript
复制
func FormatFloat(f float64, fmt byte, prec, bitSize int) string

函数将浮点数表示为字符串并返回。

bitSize表示f的来源类型(32:float32、64:float64),会据此进行舍入。

fmt表示格式:’f’(-ddd.dddd)、’b’(-ddddp±ddd,指数为二进制)、’e’(-d.dddde±dd,十进制指数)、’E’(-d.ddddE±dd,十进制指数)、’g’(指数很大时用’e’格式,否则’f’格式)、’G’(指数很大时用’E’格式,否则’f’格式)。

prec控制精度(排除指数部分):对’f’、’e’、’E’,它表示小数点后的数字个数;对’g’、’G’,它控制总的数字个数。如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。

3.3 Parse系列函数

有了Format系列函数把一些类型转换为string类型,那么反过来Parse系列函数就是用于将字符串类型转换为给定类型的值

ParseBool()
代码语言:javascript
复制
func ParseBool(str string) (value bool, err error)

返回字符串表示的bool值。它接受1、0、t、f、T、F、true、false、True、False、TRUE、FALSE;否则返回错误。

ParseInt()
代码语言:javascript
复制
func ParseInt(s string, base int, bitSize int) (i int64, err error)

返回字符串表示的整数值,接受正负号。

base指定进制(2到36),如果base为0,则会从字符串前置判断,”0x”是16进制,”0”是8进制,否则是10进制;

bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;

返回的err是*NumErr类型的,如果语法有误,err.Error = ErrSyntax;如果结果超出类型范围err.Error = ErrRange。

ParseUnit()
代码语言:javascript
复制
func ParseUint(s string, base int, bitSize int) (n uint64, err error)

ParseUint类似ParseInt但不接受正负号,用于无符号整型。

ParseFloat()
代码语言:javascript
复制
func ParseFloat(s string, bitSize int) (f float64, err error)

3.4 Atoi()

有了int类型转字符串类型,就有字符串类型转int类型Atoi()函数用于将字符串类型的整数转换为int类型,函数签名如下。

代码语言:javascript
复制
func Atoi(s string) (i int, err error)

如果传入的字符串参数无法转换为int类型,就会返回错误。

代码语言:javascript
复制
s1 := "100"
i1, err := strconv.Atoi(s1)
if err != nil {
 fmt.Println("can't convert to int")
} else {
 fmt.Printf("type:%T value:%#v\n", i1, i1) //type:int value:100
}

除了上面常用的Format系列函数和Parse系列函数,还有Append系列函数,用法与Format类似,只是多了追加的操作。更多操作就看?官方文档吧

4.接口类型断言

Go语言的空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?

在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接口或者具体的类型

代码语言:javascript
复制
value, ok := x.(T)

x 表示一个接口类型的值(包括空接口),T 表示一个具体的类型(也可为接口类型)。

当变量是一个接口时,相比较具体类型时:

  • 具体类型→动态类型
  • 具体类型的值→动态值
代码语言:javascript
复制
func main() {
 var x interface{}
 x = "I'm Garfield"
 v, ok := x.(string)
 if ok {
  fmt.Println(v)
 } else {
  fmt.Println("Asserts Failed")
 }
}

上面的示例中如果要多次断言就需要多个if判断,Go语言中中提供了另外一种断言方法switch:变量x断言成了type 类型,type 类型具体值就是 switch case 的值,如果 x 成功断言成了某个 case 类型,就可以执行那个 case,此时 i := x.(type) 返回的 i 就是那个类型的变量了,可以直接当作 case 类型使用

代码语言:javascript
复制
func justifyType(x interface{}) {
 switch i := x.(type) {
 case int64:
  fmt.Printf("x is a int64, is %v\n", i)
 case string:
  fmt.Printf("x is a string,value is %v\n", i)
 case int:
  fmt.Printf("x is a int is %v\n", i)
 case bool, int32:
  fmt.Printf("x is a bool or int32 is %v\n", i)
 case nil:
  fmt.Printf("x is a interface{} is %v\n", i)
 default:
  fmt.Println("unsupport type!")
}

func main() {
    justifyType(nil)
    justifyType("I'm Garfield")
    justifyType(44)
    justifyType(int64(516165161616))
    justifyType(true)
    justifyType(int32(1105020))
}

5.接口类型检测

除此之外,开发者还可以像C#那样把实现了接口的实例赋值给接口变量,前面博文中介绍过利用编译器和匿名变量,判断结构体是否实现了接口,实质也就是利用这种方式做一个接口类型检测:

代码语言:javascript
复制
var _ IRouter = &Engine{}

类似的还有:

代码语言:javascript
复制
var _ IRouter = (*Engine)(nil)

nil的类型是 nil,地址值为0x0,利用强制类型转换成了 *Engine ,返回的变量就是类型为 *Engine 地址值为0x0,如果 *Engine 没有实现了 IRouter 接口,就会在编译时报错,上面两个看似不同的代码,其本质是一样的,目的也一致:实现在编译期间检测接口是否实现

参考链接

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/types/casting-and-type-conversions

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/type-testing-and-cast#cast-expression

------------------- End -------------------

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 加菲的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.C#中的类型转换
  • 2.Go语言中的类型转换
    • 简单转换
    • 3.strconv包
      • 3.1 Itoa()
        • 3.2 FormatInt()
          • Format系列函数
        • 3.3 Parse系列函数
          • 3.4 Atoi()
          • 4.接口类型断言
          • 5.接口类型检测
          • 参考链接
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档