golang中使用for range 遍历字符串时常遇到的bug,byte和rune类型,源码分析

本文分析了在Golang中使用forrange遍历字符串时,将fori,_:=range转换为fori,x:=range导致的错误,解释了byte和rune类型的区别,以及如何处理字符串作为字节数组的特殊性。
摘要由CSDN通过智能技术生成

golang中使用for range 遍历字符串时常遇到的bug,byte和rune类型,源码分析

在leetcode刷题时,刷到第13题罗马数字转整数

在如下代码中可以通过,

func romanToInt(s string) int {
    ans := 0
    // 1.创建一个map表示字母到数字的映射
    cnt := map[byte]int{
        'I' : 1,
        'V' : 5,
        'X' : 10,
        'L' : 50,
        'C' : 100,
        'D' : 500,
        'M' : 1000,
    }
    n := len(s)
    for i := range s{
        value := cnt[s[i]]
        if i < n-1 && value < cnt[s[i+1]]{
            ans -= value
        }else{
            ans += value
        }
    }
    return ans 
    
}

但是将上述代码中for i := range s{}转换成为for i, x := range s {}后代码通过不了,即为如下代码

func romanToInt(s string) int {
    ans := 0
    // 1.创建一个map表示字母到数字的映射
    cnt := map[byte]int{
        'I' : 1,
        'V' : 5,
        'X' : 10,
        'L' : 50,
        'C' : 100,
        'D' : 500,
        'M' : 1000,
    }
    n := len(s)
    for i, x := range s{
        value := cnt[x]  //通过 x直接引用该元素
        if i < n-1 && value < cnt[s[i+1]]{
            ans -= value
        }else{
            ans += value
        }
    }
    return ans 
    
}

会提示如下错误

Line 15: Char 22: cannot use x (variable of type rune) as byte value in map index (solution.go)

错误原因

根据错误提示为显示为,数据类型不符,我们都知道在go语言中字符串为字符数组,我们也可以将它理解成一个由字符组成的数组,字符串是由字符组成的数组,C 语言中的字符串使用字符数组 char[] 表示。数组会占用一片连续的内存空间,而内存空间存储的字节共同组成了字符串,Go 语言中的字符串只是一个只读的字节数组

查阅资料后发现:遍历字符串的过程与数组、切片和哈希表非常相似,只是在遍历时会获取字符串中索引对应的字节并将字节转换成 rune。我们在遍历字符串时拿到的值都是 rune 类型的变量,for i, r := range s {} 的结构都会被转换成如下所示的形式:

ha := s
for hv1 := 0; hv1 < len(ha); {
    hv1t := hv1
    hv2 := rune(ha[hv1])
    if hv2 < utf8.RuneSelf {
        hv1++
    } else {
        hv2, hv1 = decoderune(ha, hv1)
    }
    v1, v2 = hv1t, hv2
}

字符串是一个只读的字节数组切片,所以范围循环在编译期间生成的框架与切片非常类似,只是细节有一些不同。

使用下标访问字符串中的元素时得到的就是字节,但是这段代码会将当前的字节转换成 rune 类型。如果当前的 rune 是 ASCII 的,那么只会占用一个字节长度,每次循环体运行之后只需要将索引加一,但是如果当前 rune 占用了多个字节就会使用 runtime.decoderune 函数解码,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值