String用法说明

src/buildin/buildin.go文件中,对golang内建数据类型做了详细的描述,关于string的说明如下:

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string
  1. 从中我们可以获取以下信息:

    • 字符串是8比特字节的集合
    • 字符串一般但不一定是UTF-8文本
      • 个人理解,golang默认是使用UTF-8编码的,但是支持用户修改编码方式
    • 字符串可以为空"",但不能为nil
    • 字符串不可修改

string底层数据结构

type stringStruct struct {str unsafe.Pointerlen int
}
  1. String底层由两个字段组成

    • str unsafe.Pointer: 指向底层数组的指针
    • len int: 字符串长度
  2. 由底层数据结构可知,len(string)的时间复杂度是O(1)

基础函数

  1. hasPrefix(s, prefix string): 字符串s是否有前缀字符串prefix时间复杂度O(1)

    func hasPrefix(s, prefix string) bool {return len(s) >= len(prefix) && s[:len(prefix)] == prefix   // 这个 == 的原理是什么???
    }
    
  2. index(s, t string): 判断字符串t在字符串s中首次初选的位置,时间复杂度O(n)

    func index(s, t string) int {if len(t) == 0 {return 0}for i := 0; i < len(s); i++ {if s[i] == t[0] && hasPrefix(s[i:], t) {return i}}return -1
    }
    
  3. contains(s, t string) bool: 字符串s是否包含字符串t, 即通过index查看首次出现的位置时间复杂度O(n)

    func contains(s, t string) bool {return index(s, t) >= 0
    }
    
  4. stringStructOf(sp *string) *stringStruct: 获取字符串sp的底层数据结构体stringStruct

    func stringStructOf(sp *string) *stringStruct {return (*stringStruct)(unsafe.Pointer(sp))
    }
    
  5. rawstring(size int) (s string, b []byte): 获取字节大小为size的字符串

    // rawstring allocates storage for a new string. The returned
    // string and byte slice both refer to the same storage.
    // The storage is not zeroed.
    func rawstring(size int) (s string, b []byte) {p := mallocgc(uintptr(size), nil, false)   // 先分配一段内存空间,大小为size个字节,无类型,无零值stringStructOf(&s).str = p    // 将分配内存空间的地址,赋值给string的底层slice指针stringStructOf(&s).len = size  // 字符串s大小为size个字节*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}  // 同时,定义一个slice类型(也指向同一个地址空间)赋值给breturn
    }
    

    rawstring函数给一个新字符串分配存储,返回一个字符串和一个字节slice,两者指向同一个内存空间,存储空间没有初始化零值(mallocgc函数未初始化零值)

  6. stringDataOnStack(s string): 字符串s是否在当前goroutine的栈上

    func stringDataOnStack(s string) bool {ptr := uintptr(stringStructOf(&s).str)  // 获取字符串s的指针地址stk := getg().stack  // 获取当前goroutine的栈指针return stk.lo <= ptr && ptr < stk.hi  // 字符串s的地址是否在栈的高低地址之间
    }
    
  7. slicebytetostringtmp: 把字节slice转换成字符串。其实就是把字节slice的指针赋值给字符串s的地址指针,再加上长度n即可

    func slicebytetostringtmp(ptr *byte, n int) (str string) {stringStructOf(&str).str = unsafe.Pointer(ptr)stringStructOf(&str).len = nreturn
    }
    

string拼接x + y + z

func concatstrings(buf *tmpBuf, a []string) string {idx := 0l := 0count := 0for i, x := range a {n := len(x)if n == 0 {continue}if l+n < l {throw("string concatenation too long")}l += ncount++idx = i}if count == 0 {return ""}if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {return a[idx]}s, b := rawstringtmp(buf, l)for _, x := range a {copy(b, x)b = b[len(x):]}return s
}

多个字符串拼接,其原理是先遍历所有子字符串,获取其长度l后,先在内存中分配长度l的内存空间,然后将子字符串依次赋值到新空间内。时间复杂度为O(n)

string转slice

// 定义了默认缓冲区大小为32bytes
const tmpStringBufSize = 32
type tmpBuf [tmpStringBufSize]byte// string => Slice
func stringtoslicebyte(buf *tmpBuf, s string) []byte {var b []byte// 如果字符串长度小于32bytes,直接使用默认缓冲区if buf != nil && len(s) <= len(buf) {*buf = tmpBuf{}b = buf[:len(s)]} else {// 如果字符换长度大于32bytes,需要新申请一块内存区域b = rawbyteslice(len(s))}// 始终产生一次数据拷贝copy(b, s)return b
}// 重新申请一块内存,构建新的byte slice
func rawbyteslice(size int) (b []byte) {cap := roundupsize(uintptr(size))p := mallocgc(cap, nil, false)if cap != uintptr(size) {memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))}*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}return
}

slice转string

func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) {...var p unsafe.Pointer// 如果字节数小于32,直接使用缓冲区if buf != nil && n <= len(buf) {p = unsafe.Pointer(buf)} else {// 否则,重新申请内存p = mallocgc(uintptr(n), nil, false)}// 构建string,内存为tmp地址或新申请内存地址,长度为nstringStructOf(&str).str = pstringStructOf(&str).len = n// 从ptr指针拷贝n个字节到p指针,也存在一次数据拷贝memmove(p, unsafe.Pointer(ptr), uintptr(n))return
}

Golang源码阅读笔记 - String相关推荐

  1. syzkaller 源码阅读笔记1(syz-extract syz-sysgen)

    文章目录 1. syz-extract 1-0 总结 1-1. `main()` 1-2 `archList()` - `1-1 (3)` 获取架构 name list 1-3 `createArch ...

  2. 代码分析:NASM源码阅读笔记

    NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...

  3. Yii源码阅读笔记 - 日志组件

    2015-03-09 一 By youngsterxyf 使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category); Yii: ...

  4. 【Flink】Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型

    1.概述 转载:Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型 相似文章:[Flink]Flink 基于 MailBox 实现的 StreamTask 线程模型 Fl ...

  5. 【Flink】Flink 源码阅读笔记(15)- Flink SQL 整体执行框架

    1.概述 转载:Flink 源码阅读笔记(15)- Flink SQL 整体执行框架 在数据处理领域,无论是实时数据处理还是离线数据处理,使用 SQL 简化开发将会是未来的整体发展趋势.尽管 SQL ...

  6. Android TV TIF源码阅读笔记

                                   Android TV TIF源码阅读笔记 1.SystemSever.java if (mPackageManager.hasSystem ...

  7. go源码阅读笔记(unsafe)

    go源码阅读笔记(unsafe) unsafe 包主要是可以使得用户绕过go的类型规范检查,能够对指针以及其指向的区域进行读写操作. package mathimport "unsafe&q ...

  8. svf源码阅读笔记(一)

    svf源码阅读笔记(一) SVF/tools/Example/svf-ex.cpp 驱动程序 int main(int argc, char ** argv) {int arg_num = 0;cha ...

  9. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

最新文章

  1. wubantu18.04版,pycharm2.18.3.2永久破解来了,借鉴个位大神的教程破掉的,感谢各位大佬...
  2. xbox acc驱动win7_Xbox老大:希望第一方工作室能推出更多单机游戏_电竞
  3. BUUCTF 特殊的BASE64
  4. 查询Oracle正在执行的sql语句,锁表,解锁
  5. python sqlite
  6. 阿里云专有网络环境下不同账号之间内网互通(内网高速通道)
  7. VirusTotal 共享8000万勒索软件样本分析数据库
  8. MySQL优化详解(四)——MySQL缓存设置
  9. C语言题目:5-7 购物(二) (25 分)
  10. 用selenium实现百度贴吧自动发帖
  11. iMazing怎么恢复备份?iMazing恢复备份教程分享
  12. 程序员日常工作总结2020-01-21
  13. PHP获取客户端真实 IP 地址
  14. 关于HTML的一些知识
  15. python中的特殊用法
  16. C4D R25调节网格间距的方法
  17. 数字后端基本概念介绍Tie cell
  18. 深入探索C语言struct的用法
  19. ALBRECHT密钻夹头SK30 2-14mm A92
  20. 安卓碎片(Fragment)的使用

热门文章

  1. C语言之scanf超详细解析
  2. 小学计算机六年级下教学计划,人教版小学六年级下册信息技术教学计划范文(通用3篇)...
  3. ZIP压缩包设置密码和删除密码
  4. JAVA swing实现简单的学生管理系统
  5. InvalidateRect()与Invalidate()的用法(转)
  6. 判断素数———两种高效算法
  7. pytorch深度学习入门与实战——今天我们来对一张图像进行卷积、池化,以及激活层的使用展示
  8. 十年风雨,一个普通程序员的成长之路(一)怀念:西安的小黑屋
  9. 和尚啃源码 之 RM深大开源RP_Infantry_Plus
  10. 人员管理KPI和OKR