国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站開(kāi)發(fā)費(fèi)用清單淘寶指數(shù)官網(wǎng)

網(wǎng)站開(kāi)發(fā)費(fèi)用清單,淘寶指數(shù)官網(wǎng),哈爾濱網(wǎng)站開(kāi)發(fā),東莞網(wǎng)站建設(shè) 包裝材料g o l a n g golang golang的 s t r i n g string string類(lèi)型是不可修改的,對(duì)于拼接字符串來(lái)說(shuō),本質(zhì)上還是創(chuàng)建一個(gè)新的對(duì)象將數(shù)據(jù)放進(jìn)去。主要有以下幾種拼接方式 拼接方式介紹 1.使用 s t r i n g string string自帶的運(yùn)算符 ans ans s2. 使用…

g o l a n g golang golang s t r i n g string string類(lèi)型是不可修改的,對(duì)于拼接字符串來(lái)說(shuō),本質(zhì)上還是創(chuàng)建一個(gè)新的對(duì)象將數(shù)據(jù)放進(jìn)去。主要有以下幾種拼接方式

拼接方式介紹

1.使用 s t r i n g string string自帶的運(yùn)算符 + + +

ans = ans + s

2. 使用格式化輸出 f m t . S p r i n t f fmt.Sprintf fmt.Sprintf

ans = fmt.Sprintf("%s%s", ans, s)

3. 使用 s t r i n g s strings strings j o i n join join函數(shù)

一般適用于將字符串?dāng)?shù)組轉(zhuǎn)化為特定間隔符的字符串的情況

ans=strings.join(strs,",")

4. 使用 s t r i n g s . B u i l d e r strings.Builder strings.Builder

builder := strings.Builder{}
builder.WriteString(s)
return builder.String()

5. 使用 b y t e s . B u f f e r bytes.Buffer bytes.Buffer

buffer := new(bytes.Buffer)
buffer.WriteString(s)
return buffer.String()

6. 使用 [ ] b y t e []byte []byte,并且提前設(shè)置容量

ans := make([]byte, 0, len(s)*n)
ans = append(ans, s...)

性能對(duì)比

先寫(xiě)一個(gè)隨機(jī)生成長(zhǎng)度為 n n n的字符串的函數(shù)

func getRandomString(n int) string {var tmp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"ans := make([]uint8, 0, n)for i := 0; i < n; i++ {ans = append(ans, tmp[rand.Intn(len(tmp))])}return string(ans)
}

接下來(lái)分別寫(xiě)出上述拼接方式的實(shí)現(xiàn),假設(shè)每次都拼接n次字符串s后返回。

1.使用 s t r i n g string string自帶的運(yùn)算符 + + +

循環(huán) n n n次,每次都令答案字符串 a n s + ans+ ans+源字符串 s s s

func plusOperatorJoin(n int, s string) string {var ans stringfor i := 0; i < n; i++ {ans = ans + s}return ans
}

2. 使用格式化輸出 f m t . S p r i n t f fmt.Sprintf fmt.Sprintf

循環(huán) n n n次,使用 f m t . S p r i n t f fmt.Sprintf fmt.Sprintf達(dá)到拼接的目的

func sprintfJoin(n int, s string) string {var ans stringfor i := 0; i < n; i++ {ans = fmt.Sprintf("%s%s", ans, s)}return ans
}

3. 使用 s t r i n g s strings strings j o i n join join函數(shù)

拼接同一個(gè)字符串的話(huà)不適合用 j o i n join join函數(shù),所以跳過(guò)這種方式

4. 使用 s t r i n g s . B u i l d e r strings.Builder strings.Builder

初始化 s t r i n g s . B u i l d e r strings.Builder strings.Builder,循環(huán) n n n次,每次調(diào)用 W r i t e S t r i n g WriteString WriteString方法

func stringBuilderJoin(n int, s string) string {builder := strings.Builder{}for i := 0; i < n; i++ {builder.WriteString(s)}return builder.String()
}

5. 使用 b y t e s . B u f f e r bytes.Buffer bytes.Buffer

初始化 b y t e s . B u f f e r bytes.Buffer bytes.Buffer,循環(huán) n n n次,每次調(diào)用 W r i t e S t r i n g WriteString WriteString方法

func bytesBufferJoin(n int, s string) string {buffer := new(bytes.Buffer)for i := 0; i < n; i++ {buffer.WriteString(s)}return buffer.String()
}

6. 使用 [ ] b y t e []byte []byte,并且提前設(shè)置容量

定義 a n s ans ans b y t e byte byte數(shù)組,并提前設(shè)置容量為 l e n ( s ) ? n len(s)*n len(s)?n

func bytesJoin(n int, s string) string {ans := make([]byte, 0, len(s)*n)for i := 0; i < n; i++ {ans = append(ans, s...)}return string(ans)
}

測(cè)試代碼

先隨機(jī)生成一個(gè)長(zhǎng)度為10的字符串,然后拼接10000次。

package high_stringsimport "testing"func benchmark(b *testing.B, f func(int, string) string) {var str = getRandomString(10)for i := 0; i < b.N; i++ {f(10000, str)}
}func BenchmarkPlusOperatorJoin(b *testing.B) {benchmark(b, plusOperatorJoin)
}
func BenchmarkSprintfJoin(b *testing.B) {benchmark(b, sprintfJoin)
}
func BenchmarkStringBuilderJoin(b *testing.B) {benchmark(b, stringBuilderJoin)
}
func BenchmarkBytesBufferJoin(b *testing.B) {benchmark(b, bytesBufferJoin)
}
func BenchmarkBytesJoin(b *testing.B) {benchmark(b, bytesJoin)
}

在這里插入圖片描述

測(cè)試結(jié)果:

使用 [ ] b y t e []byte []byte > s t r i n g s . B u i l d e r strings.Builder strings.Builder >= b y t e s . B u f f e r bytes.Buffer bytes.Buffer > f m t . S p r i n t f fmt.Sprintf fmt.Sprintf > + + +運(yùn)算符

源碼分析

1.使用 s t r i n g string string自帶的運(yùn)算符 + + +

代碼在runtime\string.go


// concatstrings implements a Go string concatenation x+y+z+...
// The operands are passed in the slice a.
// If buf != nil, the compiler has determined that the result does not
// escape the calling function, so the string data can be stored in buf
// if small enough.
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 there is just one string and either it is not on the stack// or our result does not escape the calling frame (buf != nil),// then we can return that string directly.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
}
  • 首先計(jì)算拼接后的字符串長(zhǎng)度
  • 如果只有一個(gè)字符串并且不在棧上就直接返回
  • 如果 b u f buf buf不為空并且 b u f buf buf可以放下這些字符串,就把拼接后的字符串放在 b u f buf buf里,否則在堆上重新申請(qǐng)一塊內(nèi)存
func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {if buf != nil && l <= len(buf) {b = buf[:l]s = slicebytetostringtmp(&b[0], len(b))} else {s, b = rawstring(l)}return
}
// rawstring allocates storage for a new string. The returned
// string and byte slice both refer to the same storage.
// The storage is not zeroed. Callers should use
// b to set the string contents and then drop b.
func rawstring(size int) (s string, b []byte) {p := mallocgc(uintptr(size), nil, false)return unsafe.String((*byte)(p), size), unsafe.Slice((*byte)(p), size)
}
  • 然后遍歷數(shù)組,將字符串 c o p y copy copy過(guò)去

2. 使用 s t r i n g s . B u i l d e r strings.Builder strings.Builder

介紹: s t r i n g s . B u i l d e r strings.Builder strings.Builder用于使用 W r i t e Write Write方法高效地生成字符串,它最大限度地減少了內(nèi)存復(fù)制
拼接過(guò)程: b u i l d e r builder builder里有一個(gè) b y t e byte byte類(lèi)型的切片,每次調(diào)用 W r i t e S t r i n g WriteString WriteString的時(shí)候,是直接往該切片里追加字符串。因?yàn)榍衅讓拥臄U(kuò)容機(jī)制是以倍數(shù)申請(qǐng)的,所以對(duì)比1而言,2的內(nèi)存消耗要更少。
**結(jié)果返回:**在返回字符串的 S t r i n g String String方法里,是將 b u f buf buf數(shù)組轉(zhuǎn)化為字符串直接返回的。
擴(kuò)容機(jī)制: 想要緩沖區(qū)容量增加 n n n個(gè)字節(jié),擴(kuò)容后容量變?yōu)?span id="ieo6y2aa" class="katex--inline"> 2 ? l e n + n 2*len+n 2?len+n

// A Builder is used to efficiently build a string using Write methods.
// It minimizes memory copying. The zero value is ready to use.
// Do not copy a non-zero Builder.
type Builder struct {addr *Builder // of receiver, to detect copies by valuebuf  []byte
}// String returns the accumulated string.
func (b *Builder) String() string {return unsafe.String(unsafe.SliceData(b.buf), len(b.buf))
}// grow copies the buffer to a new, larger buffer so that there are at least n
// bytes of capacity beyond len(b.buf).
func (b *Builder) grow(n int) {buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)copy(buf, b.buf)b.buf = buf
}
// WriteString appends the contents of s to b's buffer.
// It returns the length of s and a nil error.
func (b *Builder) WriteString(s string) (int, error) {b.copyCheck()b.buf = append(b.buf, s...)return len(s), nil
}

3. 使用 b y t e s . B u f f e r bytes.Buffer bytes.Buffer

介紹 b y t e s . B u f f e r bytes.Buffer bytes.Buffer s t r i n g s . B u i l d e r strings.Builder strings.Builder的底層都是 b y t e byte byte數(shù)組,區(qū)別在于擴(kuò)容機(jī)制和返回字符串的 S t r i n g String String方法。
結(jié)果返回: 因?yàn)?span id="ieo6y2aa" class="katex--inline"> b y t e s . B u f f e r bytes.Buffer bytes.Buffer實(shí)際上是一個(gè)流式的字節(jié)緩沖區(qū),可以向尾部寫(xiě)入數(shù)據(jù),也可以讀取頭部的數(shù)據(jù)。所以在返回字符串的 S t r i n g String String方法里,只返回了緩沖區(qū)里未讀的部分,所以需要重新申請(qǐng)內(nèi)存來(lái)存放返回的結(jié)果。內(nèi)存會(huì)比 s t r i n g s . B u i l d e r strings.Builder strings.Builder稍慢一些。
擴(kuò)容機(jī)制: 想要緩沖區(qū)容量至少增加 n n n個(gè)字節(jié), m m m是未讀的長(zhǎng)度, c c c是當(dāng)前的容量。
優(yōu)化點(diǎn)在于如果 n < = c / 2 ? m n <= c/2-m n<=c/2?m,也就是當(dāng)前容量的一半都大于等于現(xiàn)有的內(nèi)容(未讀的字節(jié)數(shù))加上所需要增加的字節(jié)數(shù),就復(fù)用當(dāng)前的數(shù)組,把未讀的內(nèi)容拷貝到頭部去。

We can slide things down instead of allocating a new slice. We only need m+n <= c to slide, but we instead let capacity get twice as large so we don’t spend all our time copying.
我們可以向下滑動(dòng),而不是分配一個(gè)新的切片。我們只需要m+n<=c來(lái)滑動(dòng),但我們讓容量增加了一倍,這樣我們就不會(huì)把所有的時(shí)間都花在復(fù)制上。

否則的話(huà)也是 2 ? l e n + n 2*len+n 2?len+n的擴(kuò)張

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {buf      []byte // contents are the bytes buf[off : len(buf)]off      int    // read at &buf[off], write at &buf[len(buf)]lastRead readOp // last read operation, so that Unread* can work correctly.
}
// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
//
// To build strings more efficiently, see the strings.Builder type.
func (b *Buffer) String() string {if b == nil {// Special case, useful in debugging.return "<nil>"}return string(b.buf[b.off:])
}
// WriteString appends the contents of s to the buffer, growing the buffer as
// needed. The return value n is the length of s; err is always nil. If the
// buffer becomes too large, WriteString will panic with ErrTooLarge.
func (b *Buffer) WriteString(s string) (n int, err error) {b.lastRead = opInvalidm, ok := b.tryGrowByReslice(len(s))if !ok {m = b.grow(len(s))}return copy(b.buf[m:], s), nil
}// grow grows the buffer to guarantee space for n more bytes.
// It returns the index where bytes should be written.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) grow(n int) int {m := b.Len()// If buffer is empty, reset to recover space.if m == 0 && b.off != 0 {b.Reset()}// Try to grow by means of a reslice.if i, ok := b.tryGrowByReslice(n); ok {return i}if b.buf == nil && n <= smallBufferSize {b.buf = make([]byte, n, smallBufferSize)return 0}c := cap(b.buf)if n <= c/2-m {// We can slide things down instead of allocating a new// slice. We only need m+n <= c to slide, but// we instead let capacity get twice as large so we// don't spend all our time copying.copy(b.buf, b.buf[b.off:])} else if c > maxInt-c-n {panic(ErrTooLarge)} else {// Add b.off to account for b.buf[:b.off] being sliced off the front.b.buf = growSlice(b.buf[b.off:], b.off+n)}// Restore b.off and len(b.buf).b.off = 0b.buf = b.buf[:m+n]return m
}

字符串拼接性能及原理
GoLang bytes.Buffer基礎(chǔ)使用方法詳解

http://m.aloenet.com.cn/news/41870.html

相關(guān)文章:

  • 頁(yè)面模板怎么修改鄭州seo排名優(yōu)化公司
  • 威海哪家網(wǎng)站做的好北京seo招聘信息
  • 襄陽(yáng)哪里有做網(wǎng)站的手機(jī)app開(kāi)發(fā)
  • 做兼職最靠譜的網(wǎng)站淘寶網(wǎng)站的推廣與優(yōu)化
  • 學(xué)做網(wǎng)站開(kāi)發(fā)seo排名策略
  • 滄州做網(wǎng)站公司百度指數(shù)app下載
  • 商城網(wǎng)站建設(shè)咨詢(xún)網(wǎng)站seo優(yōu)化心得
  • 旅行社應(yīng)做哪些網(wǎng)站網(wǎng)絡(luò)營(yíng)銷(xiāo)成功案例分析其成功原因
  • 循環(huán)視頻做網(wǎng)站背景百度知道問(wèn)答
  • 深圳家居網(wǎng)站建設(shè)公司青島app開(kāi)發(fā)公司
  • 免費(fèi)咨詢(xún)婦科醫(yī)生在線seo推廣百度百科
  • html個(gè)人網(wǎng)站完整代碼北京網(wǎng)站優(yōu)化指導(dǎo)
  • 如何搭建一個(gè)論壇網(wǎng)站企業(yè)網(wǎng)站設(shè)計(jì)圖片
  • 沭陽(yáng)網(wǎng)站設(shè)計(jì)蘭州百度推廣的公司
  • 坪山建設(shè)網(wǎng)站網(wǎng)絡(luò)推廣員
  • wordpress 手動(dòng)安裝seo怎么做教程
  • 餐飲公司網(wǎng)站建設(shè)的特點(diǎn)免費(fèi)b站推廣網(wǎng)址有哪些
  • 網(wǎng)站底部代碼下載百度文庫(kù)首頁(yè)
  • python網(wǎng)站開(kāi)發(fā)實(shí)踐免費(fèi)網(wǎng)站申請(qǐng)域名
  • 自己做的網(wǎng)站可以有多個(gè)前端嗎網(wǎng)站建設(shè)公司是怎么找客戶(hù)
  • 網(wǎng)站建設(shè) 上市公司杭州網(wǎng)站seo外包
  • 網(wǎng)站開(kāi)發(fā)還找到工作嗎鏈網(wǎng)
  • 做網(wǎng)站建設(shè)要什么證小網(wǎng)站
  • 影樓網(wǎng)站推廣seo系統(tǒng)優(yōu)化
  • 網(wǎng)站建設(shè)方案模板高校引流軟件下載站
  • 做優(yōu)化網(wǎng)站是什么意思誰(shuí)有推薦的網(wǎng)址
  • 有什么好看的網(wǎng)站seo系統(tǒng)培訓(xùn)
  • 如何侵入網(wǎng)站服務(wù)器免費(fèi)企業(yè)黃頁(yè)查詢(xún)官網(wǎng)
  • 宜興網(wǎng)站制作百度seo優(yōu)化及推廣
  • 政府網(wǎng)站建設(shè)運(yùn)行情況寧波seo免費(fèi)優(yōu)化軟件