为了账号安全,请及时绑定邮箱和手机立即绑定

如何在防止“切片边界超出范围”错误的同时轻松地在 Go 中获取子字符串?

如何在防止“切片边界超出范围”错误的同时轻松地在 Go 中获取子字符串?

Go
qq_遁去的一_1 2021-12-07 10:49:08
使用 Go,我想将长字符串截断为任意长度(例如用于日志记录)。const maxLen = 100func main() {    myString := "This string might be longer, so we'll keep all except the first 100 bytes."    fmt.Println(myString[:10])      // Prints the first 10 bytes    fmt.Println(myString[:maxLen])  // panic: runtime error: slice bounds out of range}现在,我可以用一个额外的变量和if语句来解决它,但这似乎很冗长:const maxLen = 100func main() {    myString := "This string might be longer, so we'll keep all except the first 100 bytes."    limit := len(myString)    if limit > maxLen {        limit = maxLen    }    fmt.Println(myString[:limit]) // Prints the first 100 bytes, or the whole string if shorter}有没有更短/更清洁的方法?
查看完整描述

2 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

使用一个简单的函数来隐藏实现细节。例如,


package main


import "fmt"


func maxString(s string, max int) string {

    if len(s) > max {

        r := 0

        for i := range s {

            r++

            if r > max {

                return s[:i]

            }

        }

    }

    return s

}


func main() {

    s := "日本語"

    fmt.Println(s)

    fmt.Println(maxString(s, 2))

}

输出:


日本語

日本


查看完整回答
反对 回复 2021-12-07
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

假设您想保留最多的maxLen字符,即您的代码所说的内容,而不是您的字符串所说的内容。


如果你不需要原来的 myString,你可以像这样覆盖它:


const maxLen = 100


func main() {

    myString := "This string might be longer, so we'll keep the first 100 bytes."


    if len(myString) >= maxLen {

        myString = myString[:maxLen] // slicing is a constant time operation in go

    }


    fmt.Println(myString) // Prints the first 100 bytes, or the whole string if shorter

}

这可能会将 unicode 字符减半,最后留下一些垃圾。如果您需要处理多字节 unicode(您可能会这样做),请尝试以下操作:


func main() {

    myString := "日本語"


    mid := maxLen

    for len(myString) >= mid && utf8.ValidString(myString[:mid]) == false {

        mid++ // add another byte from myString until we have a whole multi-byte character

    }

    if len(myString) > mid {

        myString = myString[:mid]

    }


    fmt.Println(myString) // Prints the first 100 bytes, or the whole string if shorter

}

或者,如果您可以接受从输出中删除最多一个字符,则此版本会更简洁一些


func main() {

    myString := "日本語"


    for len(myString) >= maxLen || utf8.ValidString(myString) == false {

        myString = myString[:len(myString)-1] // remove a byte

    }


    fmt.Println(myString) // Prints the first 100 bytes, or the whole string if shorter

}


查看完整回答
反对 回复 2021-12-07
  • 2 回答
  • 0 关注
  • 209 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信