设为首页 加入收藏

TOP

类型转换和类型断言(一)
2019-05-23 14:35:11 】 浏览:131
Tags:类型 转换 断言

概述


 

 

由于Go语言不允许隐式类型转换,不同的类型之间的转换必须做显示的类型转换。而类型转换和类型断言的本质,就是把一个类型转换到另一个类型。

不过Go语言必须做显示的类型转换的要求也有例外的情况:

  •  当普通 T 类型变量向 I 接口类型转换时,是隐式转换的(编译时转换);(T->I)
  • 当 IX 接口变量向I接口类型转,是隐式转换的(编译完成时转换的);(I->I)

 

类型之间转换的例子

下面是Go语言规范给出的部分例子:

*Point(p)        // same as *(Point(p))
(*Point)(p)      // p is converted to *Point
<-chan int(c)    // same as <-(chan int(c))
(<-chan int)(c)  // c is converted to <-chan int
func()(x)        // function signature func() x
(func())(x)      // x is converted to func()
(func() int)(x)  // x is converted to func() int
func() int(x)    // x is converted to func() int (unambiguous)

  

简单的说, x需要转换为T类型的语法是T(x)
如果对于某些地方的优先级拿不准可以自己加()约束.

最后一个转换就是一个容易混淆的语句, 因此需要用括号(func() int)(x)提高优先级.

还有一个容易混淆的地方是 只读和只写的通道类型 <-chan int/chan<- int .

 

 

变量类型转换方式


 

 

Go语言的转换分两种:类型转换 和 类型断言

 

1. 类型转换

 

go里面的类型转换写法:

T(x)

  

 

(1)、语法:<结果类型> := <目标类型> ( <表达式> )

(2)、类型转换是用来在不同但相互兼容的类型之间的相互转换的方式,所以,当类型不兼容的时候,是无法转换的。如下:

var var1 int = 7
fmt.Printf("%T->%v\n", var1, var1)  //int->7
var2 := float32(var1) 
fmt.Printf("%T->%v\n", var2, var2) //float32->7

  

值得注意的是,如果某些类型可能引起误会,应该用括号括起来转换,如下:

//创建一个int变量,并获得它的指针
var1 := new(int32)
fmt.Printf("%T->%v\n", var1, var1)
var2 := *int32(var1)
fmt.Printf("%T->%v\n", var2, var2)

  

*int32(var1)相当于*(int32(var1)),一个指针,当然不能直接转换成一个int32类型,所以该表达式直接编译错误。将该表达式改为 (*int32)(var1)就可以正常输出了。

 

2. 类型断言(Type Assertion)

类型断言用于提取接口的基础值 

go里面的类型断言写法:

x.(T)

其中x为interface{}类型,T是要断言的类型。

 

(1)语法

  <目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言

  <目标类型的值> := <表达式>.( 目标类型 )  //非安全类型断言

(2)类型断言的本质,跟类型转换类似,都是类型之间进行转换,不同之处在于,类型断言实在接口之间进行,相当于Java中,对于一个对象,把一种接口的引用转换成另一种。

 

x.(T) 检查x的动态类型是否是T,其中x必须是接口值。

 

我们先来看一个最简单的错误的类型断言:

func test() {
    var i interface{} = "kk"
    j := i.(int)
    fmt.Printf("%T->%d\n", j, j)
}

  

var i interface{} = "KK" 某种程度上相当于java中的,Object i = "KK";

现在把这个 i 转换成 int 类型,系统内部检测到这种不匹配,就会调用内置的panic()函数,抛出一个异常。

改一下,把 i 的定义改为:var i interface{} = 99,就没问题了。输出为:

int->99

  

以上是不安全的类型断言。我们来看一下安全的类型断言:

func test() {
    var i interface{} = "TT"
    j, b := i.(int)
    if b {
        fmt.Printf("%T->%d\n", j, j)
    } else {
        fmt.Println("类型不匹配")
    }
}

  

输出“类型不匹配”。

 

在理解有关接口的相关转换前,我们先要理解Go语言中的接口类型:interface{}

定义格式:

type IA interface {} //声明了一个接口(没有函数集合时,是空接口类型)

申明一个空接口类型时,我们在定义“空接口类型”的变量时,可以赋值任意类型的值,如

package main

import (
	"fmt"
)

type IA interface {} //空接口类型



func main()  {
	var a IA = 1  //int
	var b IA = 1.1  //float
	var c IA = false  //bool

	fmt.Println(a,b,c)
}

  

接口类型(interface{})作为函数形式参数时,则该函数可以接受任意类型的变量,但对于函数内部,该变量仍然为interface{}类型(空接口类型)

package main

import (
	"fmt"
)

func test(a interface{})  {
	fmt.Printf("%T->%v\n", a, a)
	
}


func main()  {
	test(1)
	test(1.1)
	test(true)
}

输出结果:

int->1
float64->1.1
bool->true

  

什么叫在在 函数内部,该变量任然为interface{}类型,如:

package main

import "fmt"

//用于输出数组元素
func echoArray(a interface{}){
	
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇golang语言示例 下一篇golang: 利用unsafe操作未导出变量

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目