欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

go系列教程-字符串

程序员文章站 2024-01-03 20:37:46
1、什么是字符串? Go语言中字符串是一个字节切片。把内容放在双引号""之间,我们可以创建一个字符串,让我们来看一下创建并打印字符串的简单示例。 package main import ( "fmt" ) func main() { str := "hello golang" fmt.Println ......

1、什么是字符串?

go语言中字符串是一个字节切片。把内容放在双引号""之间,我们可以创建一个字符串,让我们来看一下创建并打印字符串的简单示例。

package main

import (
    "fmt"
)

func main() {
    str := "hello golang"
    fmt.println(str)
}
在线运行程序
hello golang

2、获取字符串的每一个字节

由于字符串是一个字节切片,所以我们可以获取字符串的每一个字节

package main

import (
    "fmt"
)

func main() {
    str := "hello golang"
    printchars(str)
    fmt.println()
    printbytes(str)
    fmt.println()
    printcharsandbytes(str)
}

// 字节 %x 限定打印字符串字节
func printbytes(s string) {
    for i := 0; i < len(s); i++ {
        fmt.printf("%x ", s[i])
    }
}

// 字符  %c 限定打印字符串的字符
func printchars(s string) {
    for i := 0; i < len(s); i++ {
        fmt.printf("%c  ", s[i])
    }
}

// for range 循环是最简单方法方
func printcharsandbytes(s string) {
    for _, rune := range s {
        fmt.printf("%c starts at byte %x\n", rune, rune)
    }
}
在线运行程序
h  e  l  l  o     g  o  l  a  n  g  
68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 
h starts at byte 0
e starts at byte 1
l starts at byte 2
l starts at byte 3
o starts at byte 4
  starts at byte 5
g starts at byte 6
o starts at byte 7
l starts at byte 8
a starts at byte 9
n starts at byte a
g starts at byte b
airdemacbook-air:learn_demo wutianxiang$ go run main.go 
h  e  l  l  o     g  o  l  a  n  g  
68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 
h starts at byte 68
e starts at byte 65
l starts at byte 6c
l starts at byte 6c
o starts at byte 6f
  starts at byte 20
g starts at byte 67
o starts at byte 6f
l starts at byte 6c
a starts at byte 61
n starts at byte 6e
g starts at byte 67

如果我们再上面基础上字符串含中文,那会如何?

package main

import (
    "fmt"
)

func main() {
    str := "hello golang 语言"
    printchars(str)
    fmt.println()
    printbytes(str)
    fmt.println()
    printcharsandbytes(str)
}

// 字节 %x 限定打印字符串字节
func printbytes(s string) {
    for i := 0; i < len(s); i++ {
        fmt.printf("%x ", s[i])
    }
}

// 字符  %c 限定打印字符串的字符
func printchars(s string) {
    for i := 0; i < len(s); i++ {
        fmt.printf("%c  ", s[i])
    }
}

// for range 循环是最简单方法方
func printcharsandbytes(s string) {
    for _, rune := range s {
        fmt.printf("%c starts at byte %x\n", rune, rune)
    }
}
在线运行程序
h  e  l  l  o     g  o  l  a  n  g     è  ¯  ­  è  ¨    
68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 20 e8 af ad e8 a8 80 
h starts at byte 68
e starts at byte 65
l starts at byte 6c
l starts at byte 6c
o starts at byte 6f
  starts at byte 20
g starts at byte 67
o starts at byte 6f
l starts at byte 6c
a starts at byte 61
n starts at byte 6e
g starts at byte 67
  starts at byte 20
语 starts at byte 8bed
言 starts at byte 8a00

上面第一行输出了错误 h e l l o g o l a n g è ¯ ­ è ¨ 

为什么程序分割 hello golang 时表现完美,但分割字符含中文就错误?

这是“语言”的unicode代码点(code point)是u+00f1。他的utf-8编码占用了 e8 af ad e8 a8 80

6个字节。

它的utf-8编码占用了8个字节 e8 af ad e8 a8 80。而我们打印字符时,却假定每个字符的编码只会占用一个字节,这是错误的。

在utf-8编码中,一个代码点可能会占用超过一个字节的空间。

那么我们该怎么办呢?

rune 能帮我们解决这个难题。

rune是go语言的内建类型,它是int32的别称。在go语言中,rune表示一个代码点,无论代码点占用多少个字节,都可以用一个rune来表示

package main

import (
    "fmt"
)

func main() {
    str := "hello golang 语言"
    printchars(str)
    fmt.println()
    printbytes(str)
    fmt.println()
    printcharsandbytes(str)
}

// 字节 %x 限定打印字符串字节
func printbytes(s string) {
    for i := 0; i < len(s); i++ {
        fmt.printf("%x ", s[i])
    }
}

// 字符  %c 限定打印字符串的字符
func printchars(s string) {
    runes := []rune(s)
    for i := 0; i < len(runes); i++ {
        fmt.printf("%c  ", runes[i])
    }
}

// for range 循环是最简单方法方
func printcharsandbytes(s string) {
    for _, rune := range s {
        fmt.printf("%c starts at byte %x\n", rune, rune)
    }
}
在线运行程序
h  e  l  l  o     g  o  l  a  n  g     语  言  
68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 20 e8 af ad e8 a8 80 
h starts at byte 68
e starts at byte 65
l starts at byte 6c
l starts at byte 6c
o starts at byte 6f
  starts at byte 20
g starts at byte 67
o starts at byte 6f
l starts at byte 6c
a starts at byte 61
n starts at byte 6e
g starts at byte 67
  starts at byte 20
语 starts at byte 8bed
言 starts at byte 8a00

3、用字节切片构造字符串

package main

import (
    "fmt"
)

func main() {
    // 十六进制
    byteslice := []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x20, 0xe8, 0xaf, 0xad, 0xe8, 0xa8, 0x80}
    str := string(byteslice)
    fmt.println(str)
}
在线运行程序
hello golang 语言

4、rune 切片构造字符串

package main

import (
    "fmt"
)

func main() {
    runeslice := []rune{104, 101, 108, 108, 111, 32, 103, 111, 108, 97, 110, 103, 32, 35821, 35328}
    str := string(runeslice)
    fmt.println(str)
}
在线运行程序
hello golang 语言
5、获取字符串长度
对于字母数字组合成字符串获取长度,用len()方法;
对于中文或其它国家文字组成字符串获取长度,用utf8.runecountinstring()方法
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    str1 := "hello"
    length(str1)
    str2 := "hello您好"
    length(str2)
}

// 获取字符串长度
func length(s string) {
    fmt.printf("length of %s is %d\n", s, utf8.runecountinstring(s))
}

6、字符串是不可变的。一旦创建一个字符串,那么他将无法被修改。如果试图把字符串修改,程序会抛出一个错误:cannot assign to s[0]

package main

import (
    "fmt"
)

func main() {
    str := "hello"
    fmt.println(midfystring(str))
}

// 修改字符串
func midfystring(s string) string {
    s[0] = 'a'
    return s
}

上面这个操作是非法的。

那么如果修改字符,可以把字符串转化一个rune切片,然后对这个切片任何修改,再将转化一个新的字符串

package main

import (
    "fmt"
)

func main() {
    str := "hello"
    fmt.println(midfystring(str))
    fmt.println(str)
}

// 修改字符串
func midfystring(s string) string {
    runes := []rune(s)
    // 注意这个是单引号。如果改成双引号,可以试试发生什么
    runes[0] = 'a'
    return string(runes)
}

7、字符串拼接,后续。。

上一篇:

下一篇: