背景

去面试的时候遇到一道和 string 相关的题目,记录一下用到的知识点。题目如下:

s:="123"
ps:=&s
b:=[]byte(s)
pb:=&b s+="4"
*ps+="5"
(*pb)[1] = 0
(*pb)[2] = 4 fmt.Printf("%+v\n",*ps)
fmt.Printf("%+v\n",*pb)

问以上代码的输出是什么。

分析

很容易可以看出 s 和 ps 代表同一个 string,b 和 pb 代表同一个 byte 的切片。关键在于

b:=[]byte(s)

根据 The Go Programming Language 的解释:

A string contains an array of bytes that, once created, is immutable. By contrast, the elements of a byte slice can be freely modified.

Strings can be converted to byte slices and back again:

s := “abc”

b := []byte(s)

s2 := string(b)

Conceptually, the []byte(s) conversion allocates a new byte array holding a copy of the bytes of s, and yields a slice that references the entirety of that array. An optimizing compiler may be able to avoid the allocation and copying in some cases, but in general copying is required to ensure that the bytes of s remain unchanged even if those of b are subsequently modified. The conversion from byte slice back to string with string(b) also makes a copy, to ensure immutability of the resulting string s2.

因为 string 是不可变的,所以不管是从 string 转到 []byte 还是从 []byte 转换到 string 都会发生一次复制。因此 p 和 b 可以看作两个内容相同的两个对象,对 p,b各自的修改不会影响对方。

先看 ps,经过两次拼接后就是 "12345"。

再看 pb,因为 s 中的内容都是 ASCII 字符,在 b 中只需要用一个 byte 就可以表示一个字符,所以 b 的实际内容是[49,50,51],分别对应1,2,3的 ASCII 编码。经过就修改后就变成了[49,0,4]。

答案

经过上面的分析,最后输出的答案是"12345"和[49,0,4]

延伸

题目中对字符串的拼接也是常用的场景。因为 string 是不可变的,所以在拼接字符串时实际上也是将源字符串复制了一次,所以在 string 比较大时会消耗不少的内存和时间。关于字符串拼接的各种方法这里不详细展开了,有兴趣的可以参考以下几个链接:

https://gocn.io/question/265

https://gocn.io/article/704

Reference

https://blog.golang.org/strings

https://sheepbao.github.io/post/golang_byte_slice_and_string/

http://nanxiao.me/golang-string-byte-slice-conversion/

golang 中 string 转换 []byte 的一道笔试题的更多相关文章

  1. Golang中string和[]byte的对比

    golang string和[]byte的对比 为啥string和[]byte类型转换需要一定的代价? 为啥内置函数copy会有一种特殊情况copy(dst []byte, src string) i ...

  2. Java中有关构造函数的一道笔试题解析

    Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...

  3. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

  4. Java中String转换Double类型 Java小数点后留两位

    Java中String转换Double类型 double num1 = 0.0; String qq = "19.987"; num1 = Double.valueOf(qq.to ...

  5. AS3中String转换成Boolean

    AS3中, 对布尔值的转换, 规定所有的非空字符串都是true. 下面都不行: var f:Boolean = new Boolean(str); var f:Boolean = str as Boo ...

  6. 一道笔试题和UML思想 ~

    一句软件工程界的名言,让我想起了一个和一道笔试题有关的故事.希望更多的人了解 UML 背后的思想比他的语法更重要,是笔者写作本文的一点小愿望. 一.从一句软件工程名言说起 对很多事情的处理上,东西方都 ...

  7. java中string与byte[]的转换

    1.string 转 byte[] byte[] midbytes=isoString.getBytes("UTF8"); //为UTF8编码 byte[] isoret = sr ...

  8. Java中String和byte[]间的转换浅析

    Java语言中字符串类型和字节数组类型相互之间的转换经常发生,网上的分析及代码也比较多,本文将分析总结常规的byte[]和String间的转换以及十六进制String和byte[]间相互转换的原理及实 ...

  9. Java中String和byte[]间的 转换浅析

    Java语言中字符串类型和字节数组类型相互之间的转换经常发生,网上的分析及代码也比较多,本文将分析总结常规的byte[]和String间的转换以及十六进制String和byte[]间相互转换的原理及实 ...

随机推荐

  1. 解密for循环工作机制之迭代器,以及生成器、三元表达式与列表解析、解压序列

    本节内容 1.迭代器协议与for循环 2.三元表达式 3.解压序列 4.列表解析 5.生成器 迭代器协议与for循环 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中下一项, ...

  2. 使用可变对象作为python函数默认参数引发的问题

    写python的都知道,python函数或者方法可以使用默认参数,比如 1 def foo(arg=None): 2 print(arg) 3 4 foo() 5 6 foo("hello ...

  3. Mybatis 系列8

    上篇系列7 介绍了insert.update.delete的用法, 本篇将介绍select.resultMap的用法. select无疑是我们最常用,也是最复杂的,mybatis通过resultMap ...

  4. Mybatis 系列6

    上篇系列5中 简单看了一下TypeHandler, 本次将结束对于mybatis的配置文件的学习, 本次涉及到剩下没提及到的几个节点的配置:objectFactory.databaseIdProvid ...

  5. Mybatis 系列5

    上篇系列4中 为大家介绍了mybatis中别名的使用,以及其源码.本篇将为大家介绍TypeHandler, 并简单分析其源码. Mybatis中的TypeHandler是什么? 无论是 MyBatis ...

  6. 导入项目 idea

    下的java核心编程的源码,只有java文件,没有idea或者eclipse的项目结构信息. 分别用eclipse和idea打开了一遍,方便学习调试. 项目文件夹:E:\学习资料\Java\语法\ja ...

  7. Visual Studio 和 c# 正则表达式

    今天集中说说VS生产环境下的正则. Visual Sturdio 2012以上版本查找替换 对于VS的正则,准确说,是VS2012之后的IDE下VS的正则. VS的查找和替换功能支持基础的正则表达式, ...

  8. Java io使用简介

    图:Java io概览图 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更 ...

  9. QT中的相对位置,绝对位置之间的转换(maptoglobal,mapfromglobal)

    1. 相对位置:每个Qwidget都能通过pos()获取到相对自己父类窗口的位置, 2. 绝对位置:pWidget->mapToGlobal(QPoint(0,0)) ;将当前控件的相对位置转换 ...

  10. SQL语句的CRUD

    一.基础 .说明:创建数据库 CREATE DATABASE database-name .说明:删除数据库 drop database dbname .说明:备份sql server --- 创建 ...