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 类型。

type assertions obtain the original type from the interface

这意味着在进行类型声明时,我们应该知道变量的基础类型,但情况并非总是如此。这就是为什么类型断言表达式实际上返回第二个可选值的原因:

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")
}

为什么要断言?

在上面的例子中,它可能看起来像你“转换”的类型greetinginterface{}intstring。但是,的类型greeting是固定的,并且与初始化期间声明的相同。

分配greeting接口类型时,请勿更改其基础类型。 同样声明其类型时,您只是在使用整个原始类型功能,而不是使用接口公开的有限方法。

类型转换

首先,让我们花点时间了解一下什么是“类型”。go中的每种类型都定义了两件事:

  1. 变量的存储方式(基础数据结构)
  2. 您可以使用变量做什么(可以使用的方法和函数)

有几个,其中stringint包括在内。以及复合类型,包括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)

这个imyint类型,但是originalintint类型。

types can be converted as long as they have the same underlying data structure

什么时候可以使用类型转换?

如果基础结构相同,类型之间可以相互转换 。让我们来看一个使用结构的示例:

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体育官方入口。

原文地址:

译文地址:https://learnku.com/go/t/52387

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 2

机翻味太重

2年前
9个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
网站地图