.(data_type)方法具体是做什么的?

huangapple go评论67阅读模式
英文:

What exactly does .(data_type) method called/do?

问题

我遇到了一段使用.(string)方法的代码。由于不知道这个方法的名称,我在搜索时遇到了困难。

这是我试图理解它的方式:

package main

import "fmt"
import "reflect"

func main(){
    var b interface{}
    b = "silly"

    fmt.Println(reflect.TypeOf(b.(string))) // 我们知道b在编译时是一个字符串

    fmt.Println(reflect.TypeOf(b))          // 我们不知道
}

结果:

string
string

然而,我认为reflect.TypeOf是在运行时发生的,而.(string)会告诉编译器b确实是一个字符串,这可以用来告诉编译器变量的某种类型。我的理解正确吗?

goplayground

英文:

I came a cross a piece of code that used .(string) method. Not knowing what this is called I had difficulties searching for it.

Here is my try to understand it:

package main

import "fmt"
import "reflect"

func main(){
	var b interface{}
	b = "silly"

	fmt.Println(reflect.TypeOf(b.(string))) // we know that b 
                                            // is a string                     
                                            // at compile time

	fmt.Println(reflect.TypeOf(b))          // we do not
	
}

Result:

string
string

However, I think that reflect.TypeOf takes place at run time, while .(string) would tell the compiler that b is indeed a string, and this could be used to tell the compiler that a variable is of certain type. Is my understanding right?

goplayground

答案1

得分: 15

b.(string)被称为**类型断言。正如在Effective Go**中所述:

类型断言从接口值中提取指定显式类型的值。

因此,是的,从类型断言中获取的值不是接口值,而是显式类型的值。您还可以通过添加一个无类型布尔值来测试类型断言是否成功:

s, ok := b.(string) // s 的类型是 string
if !ok {
    // b 不包含 string 类型的值!
}

编辑:

为了进一步解释以消除可能的误解:

正如您所提到的,类型断言并不是告诉 Go b 是一个字符串。它的作用是在运行时尝试从 b 中提取一个字符串,并在 b 包含其他类型时引发 panic(除非分配了可选的布尔值)。

从断言中获取的值确实是 string 类型,这使您可以执行诸如切片操作(无法对接口值进行切片)或检查其 len 等操作。

英文:

b.(string) is called a type assertion. As written in Effective Go:

>A type assertion takes an interface value and extracts from it a value of the specified explicit type.

So, yes, the value you get from a type assertion is not an interface value, but is of the explicit type. You can also test if the type assertion was successful by adding an untyped boolean value:

s, ok := b.(string) // s is of type string
if !ok {
    // b did not contain a value of type string!
}

Edit:

To explain further to clear out any possible misunderstanding:

A type assertion doesn't "tell Go that b is a string" as you suggested. What it does is that it will, in run time, try to extract a string from b, and panic if b contains some other type (unless assigning the optional bool value).

The value that you get from the assertion will indeed be of type string, allowing you to do things like slicing (you cannot slice an interface value) or checking its len.

答案2

得分: 2

之前的答案是正确的。但是我提交这个更像是实际情况中发生的情况。在 switch 语句中,通常会使用 .(type) 语法来处理类型名称。在这个例子中,I(整数表达式)、B(布尔表达式)和Bop(二元操作符)都是类型名称。

func commute(e Expr) (r Expr, d bool) {
    switch exp := e.(type) {
    case I:
        r, d = exp, false
    case B:
        r, d = exp, false
    case Bop:
        r, d = Bop{exp.op, exp.right, exp.left}, true
    default:
        r, d = e, false
    }
    return
}

这不像 C 语言中的强制类型转换那样不安全,因为在 case 语句内部,你可以确保具有匹配的类型。当我读取一个通道时,我经常会看到这种情况,其中通道的类型是所有 case 都实现的接口类型。

英文:

The previous answer is correct. But I submit this as more like what happens in practice. The .(type) syntax is usually used with type names in the cases of a switch. In this example, I (integer expr), B (bool expr), and Bop (binary op) are type names.

func commute (e Expr) (r Expr, d bool) {
    switch exp:= e.(type) {
        case I: r,d = exp,false
        case B: r,d = exp,false
        case Bop: r,d = Bop{exp.op, exp.right, exp.left},true
        default: r,d = e,false
    }
    return
}

This isn't unsafe like a C cast, because inside the case statement you are guaranteed to have the matching type. I see this quite a bit when reading a channel, where the type of the channel is an interface that all the cases implement.

huangapple
  • 本文由 发表于 2015年3月9日 23:43:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/28946086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定