douzhi7082 2017-03-12 05:59
浏览 43
已采纳

作为方法arg传递时,如何将未类型化的常量' '转换为字节?

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

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

Program below | Go Playground Link

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('
')
        if err != nil {
            log.Fatalln(err)
            break
        }
        fmt.Print(line)
    }

}

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

So my question is, how in the world did ' ', 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.

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

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

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?

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

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

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

Is my reasoning correct?

  • 写回答

2条回答 默认 最新

  • dongyuan9292 2017-03-12 08:50
    关注

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

    ' ' 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 " ", which is the numeric value 10:

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

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

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

    Given an expression f of function type F,

    f(a1, a2, … an)
    

    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 is an untyped constant representable by a value of type T.

    In our case this translates to:

    ' ' is an untyped (rune) constant representable by a value of type byte

    The fact that ' ' 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: constant 945 overflows byte

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP