当前位置: 首页 > news >正文

go语言中的字符串详解

目录

字符串的基本特点

1.字符串的不可变性

2.其他基本特点

字符串基本操作

1. 创建字符串

2. 获取字符串长度

3. 字符串拼接

4. 遍历字符串

5. 字符串比较

字符串常用函数

1. 判断子串

2. 查找与索引

3. 字符串替换

4. 分割与连接

5. 修剪字符串

6. 大小写转换

字符串与其他类型转换

1. 字符串转数字

2. 字符串转字节切片

3. 字节切片转字符串

4. 字符串转 Rune 切片

性能优化建议


Go 语言中,字符串是不可变的 UTF-8 编码字节序列。它提供了多种字符串操作方法和包支持,以下是 Go 中字符串操作的详细讲解。


字符串的基本特点

1.字符串的不可变性

在 Go 中,字符串一旦被创建,其内容是无法被直接修改的。这一特性源于字符串在 Go 中被设计为只读的 UTF-8 字节序列。不可变字符串避免了多线程环境下的竞态条件,字符串可以安全地在不同 Goroutines 中传递而不需要额外的同步操作。字符串不可变意味着可以缓存其哈希值或其他元数据,从而在需要多次比较时提高效率(如在 map 中用作键)。

  • 无法直接修改字符串内容 你可以通过索引访问字符串中的某个字节,但无法通过索引赋值来修改字符串内容。

    s := "hello"
    fmt.Println(s[0]) // 输出 104,对应 'h'// s[0] = 'H' // 编译错误:cannot assign to s[0]
    
  • 修改字符串会创建新的字符串 如果需要更改字符串的内容,实际上是通过创建一个新的字符串来实现的,而不是在原字符串上进行修改。

    s := "hello"
    newS := "H" + s[1:] // 创建新字符串
    fmt.Println(newS)   // 输出 "Hello"
    
  • 性能的隐性影响

    • 因为字符串不可变,每次修改字符串时都会分配新的内存来存储新字符串,频繁的字符串操作可能会导致性能问题。
    • 解决方法:对于频繁的拼接或修改操作,可以使用可变的 strings.Builder[]byte
2.其他基本特点
  1. 索引访问:可以通过索引访问字节(s[i]),但无法直接修改。
  2. 支持 Unicode:字符串是 UTF-8 编码,可以包含中文、日文等多字节字符。
  3. 零值:字符串的零值是空字符串 ""

字符串基本操作

1. 创建字符串
s1 := "Hello, World!" // 直接赋值
s2 := `这是一个
多行字符串`        // 原生字符串(支持多行,内容不转义)
2. 获取字符串长度

len() 返回字符串的字节数(注意是字节数,不是字符数)。

s := "你好"
fmt.Println(len(s)) // 输出 6,因为 "你" 和 "好" 各占 3 个字节
3. 字符串拼接

使用 +fmt.Sprintf 拼接字符串。

s1 := "Hello"
s2 := "World"
s := s1 + ", " + s2
fmt.Println(s) // 输出 "Hello, World"s3 := fmt.Sprintf("%s, %s!", s1, s2)
fmt.Println(s3) // 输出 "Hello, World!"
4. 遍历字符串
s := "你好Go"
for i := 0; i < len(s); i++ {fmt.Printf("Byte %d: %x\n", i, s[i]) // 按字节遍历
}for i, r := range s {fmt.Printf("Index %d: Rune %c\n", i, r) // 按字符遍历
}
5. 字符串比较
s1 := "abc"
s2 := "def"
fmt.Println(s1 == s2) // false
fmt.Println(s1 < s2)  // true,按字典序比较

字符串常用函数

Go 提供了内置的 strings 包来操作字符串。

1. 判断子串
  • strings.Contains:是否包含子串。
  • strings.HasPrefix:是否以子串开头。
  • strings.HasSuffix:是否以子串结尾。
import "strings"s := "hello, world"
fmt.Println(strings.Contains(s, "world"))   // true
fmt.Println(strings.HasPrefix(s, "hello")) // true
fmt.Println(strings.HasSuffix(s, "d"))     // true
2. 查找与索引
  • strings.Index:返回子串首次出现的索引,未找到返回 -1。
  • strings.LastIndex:返回子串最后出现的索引。
  • strings.Count:统计子串出现的次数。
s := "go is a good language"
fmt.Println(strings.Index(s, "good"))   // 8
fmt.Println(strings.LastIndex(s, "g")) // 17
fmt.Println(strings.Count(s, "g"))     // 3
3. 字符串替换
  • strings.Replace:替换指定子串。
  • strings.ReplaceAll:替换所有子串。
s := "hello, hello, world"
s1 := strings.Replace(s, "hello", "hi", 1)  // 替换 1 次
s2 := strings.ReplaceAll(s, "hello", "hi") // 替换所有
fmt.Println(s1) // "hi, hello, world"
fmt.Println(s2) // "hi, hi, world"
4. 分割与连接
  • strings.Split:根据分隔符分割。
  • strings.Join:将字符串切片连接。
s := "a,b,c"
parts := strings.Split(s, ",")
fmt.Println(parts) // [a b c]joined := strings.Join(parts, "-")
fmt.Println(joined) // "a-b-c"
5. 修剪字符串
  • strings.Trim:移除指定字符。
  • strings.TrimSpace:移除两端空格。
  • strings.TrimPrefixstrings.TrimSuffix:移除前缀或后缀。
s := "  hello  "
fmt.Println(strings.TrimSpace(s))        // "hello"
fmt.Println(strings.Trim(s, " h"))       // "ello"
fmt.Println(strings.TrimPrefix(s, "  ")) // "hello  "
fmt.Println(strings.TrimSuffix(s, "  ")) // "  hello"
6. 大小写转换
  • strings.ToUpper:转大写。
  • strings.ToLower:转小写。
s := "GoLang"
fmt.Println(strings.ToUpper(s)) // "GOLANG"
fmt.Println(strings.ToLower(s)) // "golang"

字符串与其他类型转换

1. 字符串转数字

使用 strconv 包。

import "strconv"n, err := strconv.Atoi("123")
if err != nil {fmt.Println("转换错误")
}
fmt.Println(n) // 123s := strconv.Itoa(456)
fmt.Println(s) // "456"
2. 字符串转字节切片
s := "hello"
b := []byte(s)
fmt.Println(b) // [104 101 108 108 111]
3. 字节切片转字符串
b := []byte{104, 101, 108, 108, 111}
s := string(b)
fmt.Println(s) // "hello"
4. 字符串转 Rune 切片
s := "你好"
r := []rune(s)
fmt.Println(r)        // [20320 22909]
fmt.Println(string(r)) // "你好"

性能优化建议

  1. 拼接大量字符串时:使用 strings.Builderbytes.Buffer,效率高于 + 拼接。
import "strings"var builder strings.Builder
builder.WriteString("hello")
builder.WriteString(", ")
builder.WriteString("world")
fmt.Println(builder.String()) // "hello, world"
  1. 避免重复操作:对字符串多次操作时,优先考虑转换为字节切片或 rune 切片操作。
http://www.lryc.cn/news/509906.html

相关文章:

  • Windows脚本清理C盘缓存
  • 分布式协同 - 分布式事务_2PC 3PC解决方案
  • 永磁同步电机负载估计算法--自适应扩张状态观测器
  • 【HarmonyOS应用开发——ArkTS语言】购物商城的实现【合集】
  • Python二维码生成器qrcode库
  • Python:模拟(包含例题:饮料换购 图像模糊 螺旋矩阵)
  • git分支与部署环境的关系以及开发规范
  • 2024最新鸿蒙开发面试题合集(一)-HarmonyOS NEXT Release(API 12 Release)
  • 【mybatis】详解 # 和 $ 的区别,两者分别适用于哪种场景,使用 $ 不当会造成什么影响
  • Java面试题,数据结构,图的最短路径算法应用于社交网络分析
  • Tree数据处理
  • idea配置gitee仓库
  • SpringBoot 事务
  • 我的JAVA-Web基础(1)
  • 【Leetcode 热题 100】207. 课程表
  • 从CreateDialogIndirectParam起---我与大模型对话
  • 重温设计模式--建造者模式
  • CSS(五):定位
  • JSON 系列之2:JSON简单查询
  • SQL 简单查询
  • YOLOv9-0.1部分代码阅读笔记-metrics.py
  • KaiOS 4.0 | DataCall and setupData implemention
  • nginx-rtmp服务器搭建
  • [c++进阶(三)]单例模式及特殊类的设计
  • 企业内训|高智能数据构建和多模态数据处理、Agent研发及AI测评技术内训-吉林省某汽车厂商
  • 009 Qt_显示类控件_QLCDNumber、ProgressBar、Calendar
  • --spring.profiles.active=prod
  • 深入解析JVM中对象的创建过程
  • 使用开源在线聊天工具Fiora轻松搭建个性化聊天平台在线交流
  • ffmpeg之显示一个yuv照片