详解为什么说Golang中的字符串类型不能修改

 更新时间:2023年03月06日 09:55:44   作者:7small7  
在接触Go这么语言,可能你经常会听到这样一句话。对于字符串不能修改,可能你很纳闷,日常开发中我们对字符串进行修改也是很正常的,为什么又说Go中的字符串不能进行修改呢?本文就来通过实际案例给大家演示一下

在接触Go这么语言,可能你经常会听到这样一句话。对于字符串不能修改,可能你很纳闷,日常开发中我们对字符串进行修改也是很正常的,为什么又说Go中的字符串不能进行修改呢?

本文就来通过实际案例给大家演示,为什么Go中的字符串不能进行修改。

在演示这个问题之前,我们先对字符串类型的基础知识做个大致的演示,这样便于大家对问题的进一步了解。

字符串定义

字符串是一种用来表示字符的数据类型。在使用时,使用" "将字符内容包含起来。例如下面的形式:

package main

import "fmt"

func main() {
    var str string = "Hello World!"
}

在Go中,字符串通常有三种定义方式:

// 第一种(全量定义)
var 变量名称 string = "字符串内容"
// 类型推导
var 变量名称 = "字符串内容"
// 短标记(只适用于局部变量)
变量名称 := "字符串内容"

字符串的定义,其实也可以通过字节的方式。这里罗列的方式是最为常见的方式。

字符串的组成

Go中的字符串符合Unicode[1]标准,并且采用UTF-8[2]编码。字符串底层其实也是由byte组成(后面会仔细讲解)。通过下面的示例,打印查看具体的字节内容:

s := "Hello World!"
for _, v := range s {
    fmt.Print(v)
    fmt.Print("\t")
}
// 72 101 108 108 111 32 87 111 114 108 100 33

上面代码打印的内容,就是每一个字符所表示的字节码。

字符串不能修改

通过上面的大致演示,我们对字符串有一个基本的了解。对于字符串不能修改,可能你很纳闷,日常开发中我们对字符串进行重新赋值也是很正常的,为什么又说Go中的字符串不能进行修改呢?

其实这里要纠正这个说话,对于字符串修改并不等价于重新赋值。开发中常用的方式,其实是一种重新赋值的概念。

str := "Hello World!"
// 重新赋值
str = "Hello Go!"
// 字符串修改
str[0] = "I"

通常听到的不能修改,其实就是指的上面代码的第二种方式。并且通过这种方式修改会报错::cannot assign to s[0] (value of type byte)

回归正题,为什么Go中的字符串不能通过下标的方式来进行修改呢? 这是因为Go中的字符串的数据结构体是由一个指针和长度组成的结构体,该指针指向的一个切片才是真正的字符串值。Go中源码有这样一段定义:

type stringStruct struct {
    str unsafe.Pointer // 指向一个byte类型的切片指针
    len int // 字符串的长度
}

正是因为底层是一个[]byte类型的切片,当我们使用下标的方式去修改值,这时候将一个字符内容赋值给byte类型,肯定是不允许的。但是我们可以通过下标的方式去访问对应的byte值。

fmt.Println(s[0]) // output:72

那我们要想通过下标的方式去修改值该怎么办呢?这时候,就需要通过切片的方式来定义,然后在转成字符串。

package main

import (  
    "fmt"
)

func main() {  
     s1 := []byte{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}
    fmt.Println(string(s1))
    // 将"H"修改为l
    s1[0] = 108
    fmt.Println(string(s1))
}
// output:
Hello World!
lello World!

字符串的赋值

上面分析了为什么字符串不能使用下标去赋值,回过来解答一下日常开发中的赋值方式。

package main

import (  
    "fmt"
)

func main() {
    // 声明一个字符串,并给与初始值
    s := "Hello World!"
    // 对变量 s 进行重新赋值
    s := "Hello Go!"
}

那为什么这种场景下又可以给字符串重新赋值呢? 这是因为,在Go的底层其实是新创建了一个[]byte{}类型的切片,将变量s中的指针指向了新的内存空间地址(也就是这里的Hello Go!)。原有的Hello World!内存空间会随着垃圾回收机制被回收掉。

为什么这么设计

可能大家都会考虑到,为什么一个普通的字符串要设计这么复杂,还需要使用指针。暂时没找到官方文档的说明,

1. 个人猜想,当遇到一个非常长的字符时,这样做使得string变得非常轻量,可以很方便的进行传递而不用担心内存拷贝。虽然在Go中,不管是引用类型还是值类型参数传递都是值传递。但指针明显比值传递更节省内存。

到此这篇关于详解为什么说Golang中的字符串类型不能修改的文章就介绍到这了,更多相关Golang字符串类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang 1.18新特性模糊测试用法详解

    Golang 1.18新特性模糊测试用法详解

    模糊测试是一种软件测试技术。其核心思想是將自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言失败,以发现可能的程序错误,比如内存泄漏,本文给大家介绍了Golang 1.18 新特性模糊测试,感兴趣的同学可以参考阅读下
    2023-05-05
  • golang关闭chan通道的方法示例

    golang关闭chan通道的方法示例

    在go语言中,通道(channel)是一个非常重要的概念,通道提供了一种在不同 goroutine 之间安全地传递数据的方式,在本文中,我们将讨论如何关闭通道以及在关闭通道时需要考虑的事项,需要的朋友可以参考下
    2024-02-02
  • golang如何修改json文件内容的方法示例

    golang如何修改json文件内容的方法示例

    这篇文章主要介绍了golang如何修改json文件内容的方法示例,使用一个例子说明golang如何访问和修改json文件,有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Go语言函数学习教程

    Go语言函数学习教程

    这篇文章主要介绍了Go语言函数基本用法,结合实例形式分析了Go语言函数的格式、定义、使用方法与相关注意事项,需要的朋友可以参考下
    2016-07-07
  • 关于golang中map使用的几点注意事项总结(强烈推荐!)

    关于golang中map使用的几点注意事项总结(强烈推荐!)

    map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用,下面这篇文章主要给大家介绍了关于golang中map使用的几点注意事项,需要的朋友可以参考下
    2023-01-01
  • Centos下搭建golang环境及vim高亮Go关键字设置的方法

    Centos下搭建golang环境及vim高亮Go关键字设置的方法

    这篇文章先给大家详细介绍了在Centos下搭建golang环境的步骤,大家按照下面的方法就可以自己搭建golang环境,搭建完成后又给大家介绍了vim高亮Go关键字设置的方法,文中通过示例代码介绍的很详细,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-11-11
  • golang架构设计开闭原则手写实现

    golang架构设计开闭原则手写实现

    这篇文章主要为大家介绍了golang架构设计开闭原则手写实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 7分钟读懂Go的临时对象池pool以及其应用场景

    7分钟读懂Go的临时对象池pool以及其应用场景

    这篇文章主要给大家介绍了关于如何通过7分钟读懂Go的临时对象池pool以及其应用场景的相关资料,文中通过示例代码介绍的非常详细,对大家学习或使用Go具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2018-11-11
  • go module构建项目的实现

    go module构建项目的实现

    本文主要介绍了go module构建项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 加速开发:使用Go语言和Gin框架构建Web项目的利器

    加速开发:使用Go语言和Gin框架构建Web项目的利器

    Go语言和Gin框架是构建高性能Web项目的利器,Go语言的简洁性和并发性,以及Gin框架的轻量级和快速路由能力,使开发者能够快速构建可靠的Web应用程序,需要的朋友可以参考下
    2023-09-09

最新评论