脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - go 迭代string数组操作 go for string[]

go 迭代string数组操作 go for string[]

2021-03-20 01:07EasternUnbeaten Golang

这篇文章主要介绍了go 迭代string数组操作 go for string[],具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

go 迭代string数组,直接拷贝去用即可

?
1
2
3
4
5
6
7
8
9
10
package main
import (
"fmt"
)
func main() {
  subsCodes := []string{"aaaa", "vvvvv", "dddd", "eeeee", "gfgggg"}
  for _, s := range subsCodes {
    fmt.Println(s)
  }
}

补充:golang字符串string与字符数组[]byte高效转换

string与[]byte的直接转换是通过底层数据copy实现的

var a = []byte("hello boy")

var b = string(a)

这种操作在并发量达到十万百万级别的时候会拖慢程序的处理速度

通过gdb调试来看一下string和[]byte的数据结构

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(gdb) l main.main
import (
  "fmt"
)
func main() {
  s := "hello, world!"
  b := []byte(s)
  fmt.Println(s, b)
(gdb) b 11
Breakpoint 1 at 0x487cd9: file /export/home/machao/src/test/strbytes.go, line 11.
(gdb) r
Starting program: /export/home/machao/src/test/test1
Breakpoint 1, main.main () at /export/home/machao/src/test/strbytes.go:11
  fmt.Println(s, b)
(gdb) info locals
s = {
str = 0x4b8ccf "hello, world!level 3 resetload64 failednil stackbaseout of memorys.allocCount=srmount errorstill in listtimer expiredtriggerRatio=unreachable: value method xadd64 failedxchg64 failed nmidlelocked= on "..., len = 13}
b = {array = 0xc4200140e0 "hello, world!", len = 13, cap = 16}
(gdb) ptype s
type = struct string {
 uint8 *str;
 int len;
}
(gdb) ptype b
type = struct []uint8 {
 uint8 *array;
 int len;
 int cap;
}

转换后 [ ]byte 底层数组与原 string 内部指针并不相同,以此可确定数据被复制。那么,如不修改数据,仅转换类型,是否可避开复制,从而提升性能?

从 ptype 输出的结构来看,string 可看做 [2]uintptr,而 [ ]byte 则是 [3]uintptr,这便于我们编写代码,无需额外定义结构类型。如此,str2bytes 只需构建 [3]uintptr{ptr, len, len},而 bytes2str 更简单,直接转换指针类型,忽略掉 cap 即可。

通过unsafe.Pointer(指针转换)和uintptr(指针运算)实现转换

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import (
  "fmt"
  "strings"
  "unsafe"
)
func str2bytes(s string) []byte {
  x := (*[2]uintptr)(unsafe.Pointer(&s))
  h := [3]uintptr{x[0], x[1], x[1]}
  return *(*[]byte)(unsafe.Pointer(&h))
}
func bytes2str(b []byte) string {
  return *(*string)(unsafe.Pointer(&b))
}
func main() {
  s := strings.Repeat("abc", 3)
  b := str2bytes(s)
  s2 := bytes2str(b)
  fmt.Println(b, s2)
}

go 迭代string数组操作 go for string[]

没有出现逃逸现象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
import (
 "testing"
 "io/ioutil"
 "time"
 "fmt"
)
var s, _ = ioutil.ReadFile("mydata4vipday.720.datx")
func test() {
 b := string(s)
 _ = []byte(b)
}
func test2() {
 b := bytes2str(s)
 _ = str2bytes(b)
}
func BenchmarkTest(b *testing.B) {
 t1 := time.Now()
 for i := 0; i < b.N; i++ {
   test()
 }
 fmt.Println("test", time.Now().Sub(t1), b.N)
}
func BenchmarkTestBlock(b *testing.B) {
 t1 := time.Now()
 for i := 0; i < b.N; i++ {
   test2()
 }
 fmt.Println("test block", time.Now().Sub(t1), b.N)
}

对比一下优化前后的性能差异

go 迭代string数组操作 go for string[]

没有额外开辟内存0B/op,执行效率:5亿次耗时1.6秒,而不用unsafe.Pointer和uintptr转换300次耗时久达到了1.1秒,效率对比高下立判

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://blog.csdn.net/EasternUnbeaten/article/details/72355127

延伸 · 阅读

精彩推荐
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09