go 中的类型断言和类型转换的差别() | go优质外文翻译 | go 技术论坛-金年会app官方网
在go中,类型断言和类型转换似乎是一个令人困惑的话题,因为它们似乎都在做相同的事情。
在本文中,我们将看到断言和转换实际上有很大的不同,并且深入了解了在go中使用它们时会发生什么。
首先,让我们看看它们的写法
这是go中的类型断言:
var greeting interface{} = "hello world"
greetingstr := greeting.(string)
这是类型转换:
greeting := []byte("hello world")
greetingstr := string(greeting)
最明显的不同是它们具有不同的语法(variable.(type)
vs type(variable)
)。让我们详细研究每种情况。
类型断言
顾名思义,类型断言用于 断言 判断一个变量是某种类型。类型断言 只能在接口上发生。
在上面的类型断言示例中, greeting
是一个interface{}
类型,我们为其分配了一个字符串。现在,我们可以说greeting
实际上是一个string
,但是向我们公开的接口是 interface{}
。
如果我们想要获取原始类型,greeting
则可以断言它是一个字符串,并且此断言返回其原始 string
类型。
这意味着在进行类型声明时,我们应该知道变量的基础类型,但情况并非总是如此。这就是为什么类型断言表达式实际上返回第二个可选值的原因:
var greeting interface{} = "42"
greetingstr, ok := greeting.(string)
第二个值ok是一个布尔值,如果我们的断言正确,则为true,否则为false。
这也意味着类型声明在运行时执行 。
类型switch
类型switch语法是一个有用的构造,可以在不确定接口类型时使用:
var greeting interface{} = 42
switch g := greeting.(type) {
case string:
fmt.println("g is a string with length", len(g))
case int:
fmt.println("g is an integer, whose value is", g)
default:
fmt.println("i don't know what g is")
}
为什么要断言?
在上面的例子中,它可能看起来像你“转换”的类型greeting
从interface{}
到int
或string
。但是,的类型greeting
是固定的,并且与初始化期间声明的相同。
分配greeting
接口类型时,请勿更改其基础类型。 同样声明其类型时,您只是在使用整个原始类型功能,而不是使用接口公开的有限方法。
类型转换
首先,让我们花点时间了解一下什么是“类型”。go中的每种类型都定义了两件事:
- 变量的存储方式(基础数据结构)
- 您可以使用变量做什么(可以使用的方法和函数)
有几个,其中string
并int
包括在内。以及复合类型,包括struct、map、array和slice。
您可以从基本类型或通过创建复合类型来声明新类型:
// myint是一个新的基础类型`int`
type myint int
// addone方法是myint使用的,但是没有声明给int
func (i myint) addone() myint { return i 1}
func main() {
var i myint = 4
fmt.println(i.addone())
}
声明myint
类型时,我们将变量结构基于基本类型int
,但更改了我们可以对myint
类型变量执行的操作(通过在其上声明新方法)。
由于myint
的底层结构是类似int
,这些类型的变量可以彼此之间转换:
var i myint = 4
originalint := int(i)
这个i
是myint
类型,但是originalint
是int
类型。
什么时候可以使用类型转换?
如果基础结构相同,则类型之间可以相互转换 。让我们来看一个使用结构的示例:
type person struct {
name string
age int
}
type child struct {
name string
age int
}
type pet {
name string
}
func main() {
bob := person{
name: "bob",
age: 15,
}
babybob := child(bob)
// "babybob := pet(bob)" 会导致编译错误
fmt.println(bob, babybob)
}
在这里,person
并且child
具有相同的数据结构,即:
struct {
name string
age int
}
因此,它们可以相互转换。
type可用于声明具有相同底层结构的多种类型:
type pet person
这仅表示child
基于相同的结构person
(类似于之前的整数示例)
为什么称为转换
如前所述,即使不同类型的底层结构可能相同,它们也具有不同的限制和定义的方法。当您从一种类型转换为另一种类型时,您将改变对类型的处理方式,而不仅仅是像类型声明中那样公开其基础类型。
如果您尝试转换为错误的类型,则类型转换还会给您带来编译错误,这与ok
类型声明所提供的运行时错误和可选返回值相反 。
结论
类型断言和类型转换之间的区别比语法上的区别更根本。它还强调了go中接口类型和非接口(或具体)类型之间的区别。
interface
类型没有任何基础数据结构,而是暴露了一个预先存在的具体类型的一些方法(它具有一个基础数据结构)。
类型断言获得了接口基础的具体类型,而类型转换改变了两个具有相同结构的类型之间的使用方式。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系金年会app官方网。
原文地址:
机翻味太重