作为方法arg传递时,如何将未类型化的常量'\ n'转换为字节? [英] How does an untyped constant '\n' get converted into a byte when passed as method arg?

查看:32
本文介绍了作为方法arg传递时,如何将未类型化的常量'\ n'转换为字节?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在观看FOSDEM '17上有关在Go中实现"tail -f"的演讲=> https://youtu.be/lLDWF59aZAo

I was watching this talk given at FOSDEM '17 about implementing "tail -f" in Go => https://youtu.be/lLDWF59aZAo

在作者的初始示例程序中,他使用文件句柄创建了 Reader ,然后使用带有分隔符'\ n'的 ReadString 方法读取文件行按行并打印其内容.我通常使用 Scanner ,所以这对我来说是新的.

In the author's initial example program, he creates a Reader using a file handle, and then uses the ReadString method with delimiter '\n' to read the file line by line and print its contents. I usually use Scanner, so this was new to me.

下面的程序|转到游乐场链接

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    fileHandle, err := os.Open("someFile.log")
    if err != nil {
        log.Fatalln(err)
        return
    }
    defer fileHandle.Close()

    reader := bufio.NewReader(fileHandle)

    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            log.Fatalln(err)
            break
        }
        fmt.Print(line)
    }

}

现在, ReadString 将字节作为分隔符参数[ https://golang.org/pkg/bufio/#Reader.ReadString]

Now, ReadString takes a byte as its delimiter argument[https://golang.org/pkg/bufio/#Reader.ReadString]

所以我的问题是,'\ n'(这是一个 rune )如何转换成 byte ?我无法解决这个问题.特别是因为 byte uint8 的别名,而 rune int32 的别名.

So my question is, how in the world did '\n', which is a rune, get converted into a byte? I am not able to get my head around this. Especially since byte is an alias for uint8, and rune is an alias for int32.

我在Gophers松弛中问了同样的问题,并被告知'\ n'不是 rune ,而是一个无类型的常量.如果我们实际上使用'\ n'创建了 rune 并将其传递进来,则编译将失败.这实际上让我更加困惑.

I asked the same question in Gophers slack, and was told that '\n' is not a rune, but an untyped constant. If we actually created a rune using '\n' and passed it in, the compilation would fail. This actually confused me a bit more.

我还获得了指向Go规范中有关类型标识=> https:/的部分的链接./golang.org/ref/spec#Type_identity

I was also given a link to a section of the Go spec regarding Type Identity => https://golang.org/ref/spec#Type_identity

如果程序不是实际的 rune ,则不应该编译该程序,为什么编译器允许无类型的常量通过?这不是不安全的行为吗?

If the program is not supposed to compile if it were an actual rune, why does the compiler allow an untyped constant to go through? Isn't this unsafe behaviour?

我的猜测是,这是由于Go规范中可分配性部分中的规则而实现的,上面写着

My guess is that this works due to a rule in the Assignability section in the Go spec, which says

x是一个无类型的常量,可以用类型T的值表示.

x is an untyped constant representable by a value of type T.

由于确实可以将'\ n'分配给 byte 类型的变量,因此将其转换.

Since '\n' can indeed be assigned to a variable of type byte, it is therefore converted.

我的推理正确吗?

推荐答案

TL; DR 您是正确的,但还有更多内容.

TL;DR Yes you are correct but there's something more.

'\ n'未键入的符文常量.它没有类型,但是是默认类型,它是 int32 ( rune int32 的别名).它包含一个表示文字"\ n"的字节,它是数值 10 :

'\n' is an untyped rune constant. It doesn't have a type but a default type which is int32 (rune is an alias for int32). It holds a single byte representing the literal "\n", which is the numeric value 10:

package main

import (
    "fmt"
)

func main() {
    fmt.Printf("%T %v %c\n", '\n', '\n', '\n') // int32 10 (newline)
}

https://play.golang.org/p/lMjrTFDZUM

规范中可以回答您问题的部分位于 §调用(重点是我的):

The part of the spec that answers your question lies in the § Calls (emphasis mine):

给出函数类型为F的表达式f,

Given an expression f of function type F,

f(a1, a2, … an)

用参数a1,a2,…an调用f.除了一个在特殊情况下,参数必须是单值表达式可分配到F的参数类型,并在函数被求值之前进行求值叫.

calls f with arguments a1, a2, … an. Except for one special case, arguments must be single-valued expressions assignable to the parameter types of F and are evaluated before the function is called.

可分配" 是此处的关键术语您引用的规范的一部分解释了它的含义.正如您正确猜到的那样,在可分配性的各种规则中,此处适用的规则如下:

"assignable" is the key term here and the part of the spec you quoted explains what it means. As you correctly guessed, among the various rules of assignability, the one that applies here is the following:

x是一个无类型的常量,可以用类型T的值表示.

x is an untyped constant representable by a value of type T.

在我们的案例中,这表示为:

In our case this translates to:

'\ n'是一个无类型(符文)常量,可以用 byte

如果我们尝试传递宽度大于1个字节的无类型符文常量,则在调用 ReadString()时实际上会将'\ n'转换为字节的事实更加明显.,到需要 byte :

The fact that '\n' is actually converted to a byte when calling ReadString() is more apparent if we try passing an untyped rune constant wider than 1 byte, to a function that expects a byte:

package main

func main() {
    foo('α')
}

func foo(b byte) {}

https://play.golang.org/p/W0EUZppWHH

上面的代码失败,并显示以下信息:

The code above fails with:

tmp/sandbox120896917/main.go:9:常量945溢出字节

tmp/sandbox120896917/main.go:9: constant 945 overflows byte

这是因为'α'实际上是2个字节,这意味着无法将其转换为 byte 类型的值(最大整数为 byte 可以容纳255,而'α'实际上是945).

That's because 'α' is actually 2 bytes, which means it cannot be converted to a value of type byte (the maximum integer a byte can hold is 255 while 'α' is actually 945).

在官方博客文章 常量 中对此进行了解释.

All this is explained in the official blog post, Constants.

这篇关于作为方法arg传递时,如何将未类型化的常量'\ n'转换为字节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆