最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語(yǔ)言中的字符串拼接方法詳情

 更新時(shí)間:2021年10月20日 16:39:16   作者:測(cè)試開(kāi)發(fā)小記  
本文介紹Go語(yǔ)言中的string類(lèi)型、strings包和bytes.Buffer類(lèi)型,介紹幾種字符串拼接方法的相關(guān)資料,需要的朋友可以參考一下,希望對(duì)你有所幫助

1、string類(lèi)型

string類(lèi)型的值可以拆分為一個(gè)包含多個(gè)字符(rune類(lèi)型)的序列,也可以被拆分為一個(gè)包含多個(gè)字節(jié) (byte類(lèi)型) 的序列。其中一個(gè)rune類(lèi)型值代表一個(gè)Unicode 字符,一個(gè)rune類(lèi)型值占用四個(gè)字節(jié),底層就是一個(gè) UTF-8 編碼值,它其實(shí)是int32類(lèi)型的一個(gè)別名類(lèi)型。

package main

import (
 "fmt"
)

func main() {
 str := "你好world"
 fmt.Printf("The string: %q\n", str)
 fmt.Printf("runes(char): %q\n", []rune(str))
 fmt.Printf("runes(hex): %x\n", []rune(str))
 fmt.Printf("bytes(hex): [% x]\n", []byte(str))
}

執(zhí)行結(jié)果:

The string: "你好world"
runes(char): ['你' '好' 'w' 'o' 'r' 'l' 'd']
runes(hex): [4f60 597d 77 6f 72 6c 64]
bytes(hex): e4 bd a0 e5 a5 bd 77 6f 72 6c 64

可以看到,英文字符使用一個(gè)字節(jié),而中文字符需要三個(gè)字節(jié)。下面使用 for range 語(yǔ)句對(duì)上面的字符串進(jìn)行遍歷:

for index, value := range str {
    fmt.Printf("%d: %q [% x]\n", index, value, []byte(string(value)))
}

執(zhí)行結(jié)果如下:

0: '你' [e4 bd a0]
3: '好' [e5 a5 bd]
6: 'w' [77]
7: 'o' [6f]
8: 'r' [72]
9: 'l' [6c]
10: 'd' [64]

index索引值不是0-6,相鄰Unicode 字符的索引值不一定是連續(xù)的,因?yàn)橹形淖址加昧?個(gè)字節(jié),寬度為3。

2、strings包

2.1 strings.Builder類(lèi)型

strings.Builder的優(yōu)勢(shì)主要體現(xiàn)在字符串拼接上,相比使用+拼接,效率更高。

  • strings.Builder已存在的值不可改變,只能重置(Reset()方法)或者拼接更多的內(nèi)容。
  • 一旦調(diào)用了Builder值,就不能再以任何方式對(duì)其進(jìn)行復(fù)制,比如函數(shù)間值傳遞、通道傳遞值、把值賦予變量等。
  • 在進(jìn)行拼接時(shí),Builder值會(huì)自動(dòng)地對(duì)自身的內(nèi)容容器進(jìn)行擴(kuò)容,也可以使用Grow方法進(jìn)行手動(dòng)擴(kuò)容。
package main

import (
 "fmt"
 "strings"
)
func main() {
 var builder1 strings.Builder
 builder1.WriteString("hello")
 builder1.WriteByte(' ')
 builder1.WriteString("world")
 builder1.Write([]byte{' ', '!'})

 fmt.Println(builder1.String()) 

 f1 := func(b strings.Builder) {
  // b.WriteString("world !")  //會(huì)報(bào)錯(cuò)
 }
 f1(builder1)

 builder1.Reset()
 fmt.Printf("The length 0f builder1: %d\n", builder1.Len())

}

執(zhí)行結(jié)果:

hello world !
The length 0f builder1: 0

2.2 strings.Reader類(lèi)型

strings.Reader類(lèi)型可以用于高效地讀取字符串,它通過(guò)使用已讀計(jì)數(shù)機(jī)制來(lái)實(shí)現(xiàn)了高效讀取,已讀計(jì)數(shù)保存了已讀取的字節(jié)數(shù),也代表了下一次讀取的起始索引位置。

package main

import (
 "fmt"
 "strings"
)
func main() { 
 reader1 := strings.NewReader("hello world!")
 buf1 := make([]byte, 6)
    fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len()))
 
    reader1.Read(buf1)
 fmt.Println(string(buf1))
    fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len()))
    
 reader1.Read(buf1)
 fmt.Println(string(buf1))
    fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len()))
}

執(zhí)行結(jié)果:

reading index: 0
hello
reading index: 6
world!
reading index: 12

可以看到,每讀取一次之后,已讀計(jì)數(shù)就會(huì)增加。

strings包的ReadAt方法不會(huì)依據(jù)已讀計(jì)數(shù)進(jìn)行讀取,也不會(huì)更新已讀計(jì)數(shù)。它可以根據(jù)偏移量來(lái)自由地讀取Reader值中的內(nèi)容。

package main

import (
 "fmt"
 "strings"
)
func main() {
    reader1 := strings.NewReader("hello world!")
    buf1 := make([]byte, 6)
 offset1 := int64(6)
 n, _ := reader1.ReadAt(buf1, offset1) 
 fmt.Println(string(buf2))
}

執(zhí)行結(jié)果:

world!

也可以使用Seek方法來(lái)指定下一次讀取的起始索引位置。

package main

import (
 "fmt"
 "strings"
    "io"
)
func main() {
    reader1 := strings.NewReader("hello world!")
    buf1 := make([]byte, 6)
 offset1 := int64(6)
 readingIndex, _ := reader2.Seek(offset1, io.SeekCurrent)
 fmt.Printf("reading index: %d\n", readingIndex)

 reader1.Read(buf1)
 fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len()))
 fmt.Println(string(buf1))
}

執(zhí)行結(jié)果:

reading index: 6
reading index: 12
world!

3、bytes.Buffer

bytes包和strings包類(lèi)似,strings包主要面向的是 Unicode 字符和經(jīng)過(guò) UTF-8 編碼的字符串,而bytes包面對(duì)的則主要是字節(jié)和字節(jié)切片,主要作為字節(jié)序列的緩沖區(qū)。bytes.Buffer數(shù)據(jù)的讀寫(xiě)都使用到了已讀計(jì)數(shù)。

bytes.Buffer具有讀和寫(xiě)功能,下面分別介紹他們的簡(jiǎn)單使用方法。

3.1 bytes.Buffer:寫(xiě)數(shù)據(jù)

strings.Builder一樣,bytes.Buffer可以用于拼接字符串,strings.Builder也會(huì)自動(dòng)對(duì)內(nèi)容容器進(jìn)行擴(kuò)容。請(qǐng)看下面的代碼:

package main

import (
 "bytes"
 "fmt"
)

func DemoBytes() {
 var buffer bytes.Buffer
 buffer.WriteString("hello ")
 buffer.WriteString("world !")
 fmt.Println(buffer.String())
}

執(zhí)行結(jié)果:

hello world !

3.2 bytes.Buffer:讀數(shù)據(jù)

bytes.Buffer讀數(shù)據(jù)也使用了已讀計(jì)數(shù),需要注意的是,進(jìn)行讀取操作后,Len方法返回的是未讀內(nèi)容的長(zhǎng)度。下面直接來(lái)看代碼:

package main

import (
 "bytes"
 "fmt"
)

func DemoBytes() {
 var buffer bytes.Buffer
 buffer.WriteString("hello ")
 buffer.WriteString("world !")
    
    p1 := make([]byte, 5)
 n, _ := buffer.Read(p1)
    
 fmt.Println(string(p1))
 fmt.Println(buffer.String())
    fmt.Printf("The length of buffer: %d\n", buffer.Len())
}

執(zhí)行結(jié)果:

hello
 world !
The length of buffer: 8

4、字符串拼接

簡(jiǎn)單了解了string類(lèi)型、strings包和bytes.Buffer類(lèi)型后,下面來(lái)介紹golang中的字符串拼接方法。

https://zhuanlan.zhihu.com/p/349672248

go test -bench=. -run=^BenchmarkDemoBytes$

4.1 直接相加

最簡(jiǎn)單的方法是直接相加,由于string類(lèi)型的值是不可變的,進(jìn)行字符串拼接時(shí)會(huì)生成新的字符串,將拼接的字符串依次拷貝到一個(gè)新的連續(xù)內(nèi)存空間中。如果存在大量字符串拼接操作,使用這種方法非常消耗內(nèi)存。

package main

import (
 "bytes"
 "fmt"
 "time"
)

func main() {
 str1 := "hello "
 str2 := "world !"
    str3 := str1 + str2
    fmt.Println(str3) 
}

4.2strings.Builder

前面介紹了strings.Builder可以用于拼接字符串:

var builder1 strings.Builder
builder1.WriteString("hello ")
builder1.WriteString("world !")

4.3 strings.Join()

也可以使用strings.Join方法,其實(shí)Join()調(diào)用了WriteString方法;

str1 := "hello "
str2 := "world !"
str3 := ""

str3 = strings.Join([]string{str3,str1},"")
str3 = strings.Join([]string{str3,str2},"")

4.4 bytes.Buffer

bytes.Buffer也可以用于拼接:

var buffer bytes.Buffer

buffer.WriteString("hello ")
buffer.WriteString("world !")

4.5 append方法

也可以使用Go內(nèi)置函數(shù)append方法,用于拼接切片:

package main

import (
 "fmt"
)

func DemoAppend(n int) {
 str1 := "hello "
 str2 := "world !"
 var str3 []byte

    str3 = append(str3, []byte(str1)...)
    str3 = append(str3, []byte(str2)...)
 fmt.Println(string(str3))
}

執(zhí)行結(jié)果:

hello world !

4.6 fmt.Sprintf

fmt包中的Sprintf方法也可以用來(lái)拼接字符串:

str1 := "hello "
str2 := "world !"
str3 := fmt.Sprintf("%s%s", str1, str2)

5、字符串拼接性能測(cè)試

下面來(lái)測(cè)試一下這6種方法的性能,編寫(xiě)測(cè)試源碼文件strcat_test.go

package benchmark

import (
 "bytes"
 "fmt"
 "strings"
 "testing"
)

func DemoBytesBuffer(n int) {
 var buffer bytes.Buffer

 for i := 0; i < n; i++ {
  buffer.WriteString("hello ")
  buffer.WriteString("world !")
 }
}

func DemoWriteString(n int) {
 var builder1 strings.Builder
 for i := 0; i < n; i++ {
  builder1.WriteString("hello ")
  builder1.WriteString("world !")
 }
}

func DemoStringsJoin(n int) {
 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 = strings.Join([]string{str3, str1}, "")
  str3 = strings.Join([]string{str3, str2}, "")
 }

}

func DemoPlus(n int) {

 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 += str1
  str3 += str2
 }
}

func DemoAppend(n int) {

 str1 := "hello "
 str2 := "world !"
 var str3 []byte
 for i := 0; i < n; i++ {
  str3 = append(str3, []byte(str1)...)
  str3 = append(str3, []byte(str2)...)
 }
}

func DemoSprintf(n int) {
 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 = fmt.Sprintf("%s%s", str3, str1)
  str3 = fmt.Sprintf("%s%s", str3, str2)
 }
}

func BenchmarkBytesBuffer(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoBytesBuffer(10000)
 }
}

func BenchmarkWriteString(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoWriteString(10000)
 }
}

func BenchmarkStringsJoin(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoStringsJoin(10000)
 }
}

func BenchmarkAppend(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoAppend(10000)
 }
}

func BenchmarkPlus(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoPlus(10000)
 }
}

func BenchmarkSprintf(b *testing.B) {
 for i := 0; i < b.N; i++ {
  DemoSprintf(10000)
 }
}


執(zhí)行性能測(cè)試:

$ go test -bench=. -run=^$
goos: windows
goarch: amd64
pkg: testGo/benchmark
cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
BenchmarkBytesBuffer-8              3436            326846 ns/op
BenchmarkWriteString-8              4148            271453 ns/op
BenchmarkStringsJoin-8                 3         402266267 ns/op
BenchmarkAppend-8                   1923            618489 ns/op
BenchmarkPlus-8                        3         345087467 ns/op
BenchmarkSprintf-8                     2         628330850 ns/op
PASS
ok      testGo/benchmark        9.279s

通過(guò)平均耗時(shí)可以看到WriteString方法執(zhí)行效率最高。Sprintf方法效率最低。

  • 我們看到Strings.Join方法效率也比較低,在上面的場(chǎng)景下它的效率比較低,它在合并已有字符串?dāng)?shù)組的場(chǎng)合效率是很高的。
  • 如果要連續(xù)拼接大量字符串推薦使用WriteString方法,如果是少量字符串拼接,也可以直接使用+。
  • append方法的效率也是很高的,它主要用于切片的拼接。
  • fmt.Sprintf方法雖然效率低,但在少量數(shù)據(jù)拼接中,如果你想拼接其它數(shù)據(jù)類(lèi)型,使用它可以完美的解決:
name := "zhangsan"
age := 20
str4 := fmt.Sprintf("%s is %d years old", name, age)
fmt.Println(str4)  // zhangsan is 20 years old

到此這篇關(guān)于Go語(yǔ)言中的字符串拼接方法詳情的文章就介紹到這了,更多相關(guān)Go語(yǔ)言中的字符串拼接方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在goland中配置gofmt的操作

    在goland中配置gofmt的操作

    這篇文章主要介紹了在goland中配置gofmt的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • 如何讓shell終端和goland控制臺(tái)輸出彩色的文字

    如何讓shell終端和goland控制臺(tái)輸出彩色的文字

    這篇文章主要介紹了如何讓shell終端和goland控制臺(tái)輸出彩色的文字的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • GO中的條件變量sync.Cond詳解

    GO中的條件變量sync.Cond詳解

    條件變量是基于互斥鎖的,它必須基于互斥鎖才能發(fā)揮作用,條件變量的初始化離不開(kāi)互斥鎖,并且它的方法有點(diǎn)也是基于互斥鎖的,這篇文章主要介紹了GO的條件變量sync.Cond,需要的朋友可以參考下
    2023-01-01
  • 從基礎(chǔ)到高級(jí)全方位解析Go中反射的應(yīng)用

    從基礎(chǔ)到高級(jí)全方位解析Go中反射的應(yīng)用

    本文我們將全面深入地探討Go語(yǔ)言的反射機(jī)制,從反射的基礎(chǔ)概念、為什么需要反射,到如何在Go中實(shí)現(xiàn)反射,以及在高級(jí)編程場(chǎng)景如泛型編程和插件架構(gòu)中的應(yīng)用,需要的可以參考下
    2023-10-10
  • 詳解golang開(kāi)發(fā)中select多路選擇

    詳解golang開(kāi)發(fā)中select多路選擇

    這篇文章主要介紹了golang開(kāi)發(fā)中select多路選擇,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • GPT回答go語(yǔ)言和C語(yǔ)言map操作方法對(duì)比

    GPT回答go語(yǔ)言和C語(yǔ)言map操作方法對(duì)比

    這篇文章主要為大家介紹了GPT回答go語(yǔ)言和C語(yǔ)言map操作方法對(duì)比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Go項(xiàng)目開(kāi)發(fā)中如何讀取應(yīng)用配置詳解

    Go項(xiàng)目開(kāi)發(fā)中如何讀取應(yīng)用配置詳解

    本文主要介紹了Go項(xiàng)目開(kāi)發(fā)中如何讀取應(yīng)用配置詳解,Go生態(tài)中有很多包可以加載并解析配置,最受歡迎的是Viper包,下面就來(lái)詳細(xì)的介紹一下
    2024-05-05
  • 利用golang實(shí)現(xiàn)封裝trycatch異常處理實(shí)例代碼

    利用golang實(shí)現(xiàn)封裝trycatch異常處理實(shí)例代碼

    Go語(yǔ)言追求簡(jiǎn)潔優(yōu)雅,所以go語(yǔ)言不支持傳統(tǒng)的 try…catch…finally 這種異常,最近發(fā)現(xiàn)了不錯(cuò)的trycatch包,下面這篇文章主要跟大家分享了關(guān)于利用golang實(shí)現(xiàn)封裝trycatch異常處理的實(shí)例代碼,需要的朋友可以參考下。
    2017-07-07
  • go語(yǔ)言實(shí)現(xiàn)依賴(lài)注入的示例代碼

    go語(yǔ)言實(shí)現(xiàn)依賴(lài)注入的示例代碼

    依賴(lài)注入和控制反轉(zhuǎn)恰恰相反,它是一種具體的編碼技巧,我們不通過(guò) new 的方式在類(lèi)內(nèi)部創(chuàng)建依賴(lài)類(lèi)的對(duì)象,而是將依賴(lài)的類(lèi)對(duì)象在外部創(chuàng)建好之后,通過(guò)構(gòu)造函數(shù)、函數(shù)參數(shù)等方式傳遞給類(lèi)來(lái)使用,本文將給大家介紹go語(yǔ)言實(shí)現(xiàn)依賴(lài)注入,需要的朋友可以參考下
    2024-01-01
  • Go語(yǔ)言基礎(chǔ)go doc命令用法及示例詳解

    Go語(yǔ)言基礎(chǔ)go doc命令用法及示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)go doc命令的用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進(jìn)步
    2021-11-11

最新評(píng)論

德令哈市| 彰化县| 庆元县| 通州区| 泰安市| 伊通| 革吉县| 明星| 鲁山县| 霍林郭勒市| 黔东| 麻江县| 紫阳县| 苏州市| 仪征市| 宣威市| 鹤庆县| 古田县| 岳池县| 海盐县| 大宁县| 泌阳县| 乐亭县| 灵璧县| 崇礼县| 湘潭县| 包头市| 宁河县| 瑞安市| 巨野县| 博罗县| 新沂市| 上犹县| 蓬溪县| 东丽区| 文安县| 晋城| 乳源| 元氏县| 伊吾县| 花莲县|