国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

go基礎(chǔ)09-Go語言的字符串類型

這篇具有很好參考價值的文章主要介紹了go基礎(chǔ)09-Go語言的字符串類型。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

字符串類型是現(xiàn)代編程語言中最常使用的數(shù)據(jù)類型之一。在Go語言的先祖之一C語言當(dāng)中,字符串類型并沒有被顯式定義,而是以字符串字面值常量或以’\0’結(jié)尾的字符類型(char)數(shù)組來呈現(xiàn)的:

#define GOAUTHERS "Robert Griesemer, Rob Pike, and Ken Thompson"
const char * s = "hello world"
char s[] = "hello gopher"


這給C程序員在使用字符串時帶來一些問題,諸如:

● 類型安全性差;

● 字符串操作要時時刻刻考慮結(jié)尾的’\0’;

● 字符串?dāng)?shù)據(jù)可變(主要指以字符數(shù)組形式定義的字符串類型);

● 獲取字符串長度代價大(O(n)的時間復(fù)雜度);

● 未內(nèi)置對非ASCII字符(如中文字符)的處理。

Go語言修復(fù)了C語言的這一“缺陷”,內(nèi)置了string類型,統(tǒng)一了對字符串的抽象。

Go語言的字符串類型

在Go語言中,無論是字符串常量、字符串變量還是代碼中出現(xiàn)的字符串字面量,它們的類型都被統(tǒng)一設(shè)置為string:

const (
	s = "string constant"
)
func main() {
	var s1 string = "string variable"
	fmt.Printf("%T\n", s) // string
	fmt.Printf("%T\n", s1) // string
	fmt.Printf("%T\n", "temporary string literal") // string
}

Go的string類型設(shè)計充分吸取了C語言字符串設(shè)計的經(jīng)驗(yàn)教訓(xùn),并結(jié)合了其他主流語言在字符串類型設(shè)計上的最佳實(shí)踐,最終呈現(xiàn)的string類型具有如下功能特點(diǎn)。

(1)string類型的數(shù)據(jù)是不可變的

一旦聲明了一個string類型的標(biāo)識符,無論是常量還是變量,該標(biāo)識符所指代的數(shù)據(jù)在整個程序的生命周期內(nèi)便無法更改。下面嘗試修改一下string數(shù)據(jù),看看能得到怎樣的結(jié)果。

我們先來看第一種方法:

func main() {
// 原始字符串
	var s string = "hello"
	fmt.Println("original string:", s)
	// 切片化后試圖改變原字符串
	sl := []byte(s)
	sl[0] = 't'
	fmt.Println("slice:", string(sl))
	fmt.Println("after reslice, the original string is:", 	string(s))
}

該程序的運(yùn)行結(jié)果如下:


original string: hello
slice: tello
after reslice, the original string is: hello

在上面的例子中,我們試圖將string轉(zhuǎn)換為一個切片并通過該切片對其內(nèi)容進(jìn)行修改,但結(jié)果事與愿違。對string進(jìn)行切片化后,Go編譯器會為切片變量重新分配底層存儲而不是共用string的底層存儲,因此對切片的修改并未對原string的數(shù)據(jù)產(chǎn)生任何影響。

我們再來試試通過更為“暴力”一些的手段對string的數(shù)據(jù)發(fā)起“攻擊”:

func main() {
// 原始string
var s string = "hello"
fmt.Println("original string:", s)
// 試圖通過unsafe指針改變原始string
modifyString(&s)
fmt.Println(s)

}



func modifyString(s *string) {
	// 取出第一個8字節(jié)的值
	p := (*uintptr)(unsafe.Pointer(s))
	// 獲取底層數(shù)組的地址
	var array *[5]byte = (*[5]byte)(unsafe.Pointer(*p))
	var len *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Sizeof((*uintptr)(nil))))
	for i := 0; i < (*len); i++ {
		fmt.Printf("%p => %c\n", &((*array)[i]), (*array)[i])
		p1 := &((*array)[i])
		v := (*p1)
		(*p1) = v + 1 //try to change the character
	}
}

我們試圖通過unsafe指針指向string在運(yùn)行時內(nèi)部表示結(jié)構(gòu)(具體參考本條后面的講解)中的數(shù)據(jù)存儲塊的地址,然后通過指針修改那塊內(nèi)存中存儲的數(shù)據(jù)。

運(yùn)行這段程序得到下面的結(jié)果:

original string: hello
0x10d1b9d => h
unexpected fault address 0x10d1b9d
fatal error: fault
[signal SIGBUS: bus error code=0x2 addr=0x10d1b9d pc=0x109b079]

我們看到,對string的底層的數(shù)據(jù)存儲區(qū)僅能進(jìn)行只讀操作,一旦試圖修改那塊區(qū)域的數(shù)據(jù),便會得到SIGBUS的運(yùn)行時錯誤,對string數(shù)據(jù)的“篡改攻擊”再次以失敗告終。

2)零值可用

Go string類型支持“零值可用”的理念。Go字符串無須像C語言中那樣考慮結(jié)尾’\0’字符,因此其零值為"",長度為0。

var s string
fmt.Println(s) // s = ""
fmt.Println(len(s)) // 0


3)獲取長度的時間復(fù)雜度是O(1)級別

Go string類型數(shù)據(jù)是不可變的,因此一旦有了初值,那塊數(shù)據(jù)就不會改變,其長度也不會改變。Go將這個長度作為一個字段存儲在運(yùn)行時的string類型的內(nèi)部表示結(jié)構(gòu)中(后文有說明)。這樣獲取string長度的操作,即len(s)實(shí)際上就是讀取存儲在運(yùn)行時中的那個長度值,這是一個代價極低的O(1)操作。

4)支持通過+/+=操作符進(jìn)行字符串連接

對開發(fā)者而言,通過+/+=操作符進(jìn)行的字符串連接是體驗(yàn)最好的字符串連接操作,Go語言支持這種操作:

s := "Rob Pike, "
s = s + "Robert Griesemer, "
s += " Ken Thompson"
fmt.Println(s) // Rob Pike, Robert Griesemer, Ken Thompson

5)支持各種比較關(guān)系操作符:==、!= 、>=、<=、>和<

func main() {
	// ==
	s1 := "世界和平"
	s2 := "世界" + "和平"
	fmt.Println(s1 == s2) // true
	// !=
	s1 = "Go"
	s2 = "C"
	fmt.Println(s1 != s2) // true
	// < 和 <=
	s1 = "12345"
	s2 = "23456"
	fmt.Println(s1 < s2) // true
	fmt.Println(s1 <= s2) // true
	// > 和 >=
	s1 = "12345"
	s2 = "123"
	fmt.Println(s1 > s2) // true
	fmt.Println(s1 >= s2) // true
}

由于Go string是不可變的,因此如果兩個字符串的長度不相同,那么無須比較具體字符串?dāng)?shù)據(jù)即可斷定兩個字符串是不同的。如果長度相同,則要進(jìn)一步判斷數(shù)據(jù)指針是否指向同一塊底層存儲數(shù)據(jù)。如果相同,則兩個字符串是等價的;如果不同,則還需進(jìn)一步比對實(shí)際的數(shù)據(jù)內(nèi)容。

6)對非ASCII字符提供原生支持

Go語言源文件默認(rèn)采用的Unicode字符集。Unicode字符集是目前市面上最流行的字符集,幾乎囊括了所有主流非ASCII字符(包括中文字符)。Go字符串的每個字符都是一個Unicode字符,并且這些Unicode字符是以UTF-8編碼格式存儲在內(nèi)存當(dāng)中的。

我們來看一個例子:

func main() {
	// 中文字符 Unicode碼點(diǎn) UTF8編碼
	// 中 U+4E2D E4B8AD
	// 國 U+56FD E59BBD
	// 歡 U+6B22 E6ACA2
	// 迎 U+8FCE E8BF8E
	// 您 U+60A8 E682A8
	s := "中國歡迎您"
	rs := []rune(s)
	sl := []byte(s)
	for i, v := range rs {
	var utf8Bytes []byte
	for j := i * 3; j < (i+1)*3; j++ {
		utf8Bytes = append(utf8Bytes, sl[j])
	}
	fmt.Printf("%s => %X => %X\n", string(v), v, utf8Bytes)
}
}

我們看到字符串變量s中存儲的文本是“中國歡迎您”五個漢字字符(非ASCII字符范疇),這里輸出了每個中文字符對應(yīng)的Unicode碼點(diǎn)(Code Point,見輸出結(jié)果的第二列),一個rune對應(yīng)一個碼點(diǎn)。UTF-8編碼是Unicode碼點(diǎn)的一種字符編碼形式,是最常用的一種編碼格式,也是Go默認(rèn)的字符編碼格式。我們還可以使用其他字符編碼格式來映射Unicode碼點(diǎn),比如UTF-16等。

在UTF-8中,大多數(shù)中文字符都使用三字節(jié)表示。[]byte(s)的轉(zhuǎn)型讓我們獲得了s底層存儲的“復(fù)制品”,從而得到每個漢字字符對應(yīng)的UTF-8編碼字節(jié)(見輸出結(jié)果的第三列)。

=> 4E2D => E4B8AD
國 => 56FD => E59BBD
歡 => 6B22 => E6ACA2
迎 => 8FCE => E8BF8E
您 => 60A8 => E682A8

7)原生支持多行字符串

Go語言直接提供了通過反引號構(gòu)造“所見即所得”的多行字符串的方法:

const s = `好雨知時節(jié),當(dāng)春乃發(fā)生。
			隨風(fēng)潛入夜,潤物細(xì)無聲。
			野徑云俱黑,江船火獨(dú)明。
			曉看紅濕處,花重錦官城。`
func main() {
	fmt.Println(s)
}

運(yùn)行結(jié)果:文章來源地址http://www.zghlxwxcb.cn/news/detail-698563.html

好雨知時節(jié),當(dāng)春乃發(fā)生。
隨風(fēng)潛入夜,潤物細(xì)無聲。
野徑云俱黑,江船火獨(dú)明。
曉看紅濕處,花重錦官城。

到了這里,關(guān)于go基礎(chǔ)09-Go語言的字符串類型的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • go基礎(chǔ)10 -字符串的高效構(gòu)造與轉(zhuǎn)換

    前面提到過,Go原生支持通過+/+=操作符來連接多個字符串以構(gòu)造一個更長的字符串,并且通過+/+=操作符的字符串連接構(gòu)造是最自然、開發(fā)體驗(yàn)最好的一種。 但Go還提供了其他一些構(gòu)造字符串的方法,比如: ● 使用fmt.Sprintf; ● 使用strings.Join; ● 使用strings.Builder; ● 使用

    2024年02月09日
    瀏覽(23)
  • 為什么說 Go 語言字符串是不可變的?

    原文鏈接: 為什么說 Go 語言字符串是不可變的? 最近有讀者留言說,平時在寫代碼的過程中,是會對字符串進(jìn)行修改的,但網(wǎng)上都說 Go 語言字符串是不可變的,這是為什么呢? 這個問題本身并不困難,但對于新手來說確實(shí)容易產(chǎn)生困惑,今天就來回答一下。 首先來看看它

    2024年02月07日
    瀏覽(19)
  • 【Golang】Golang進(jìn)階系列教程--為什么說 Go 語言字符串是不可變的?

    【Golang】Golang進(jìn)階系列教程--為什么說 Go 語言字符串是不可變的?

    最近有讀者留言說,平時在寫代碼的過程中,是會對字符串進(jìn)行修改的,但網(wǎng)上都說 Go 語言字符串是不可變的,這是為什么呢? 這個問題本身并不困難,但對于新手來說確實(shí)容易產(chǎn)生困惑,今天就來回答一下。 首先來看看它的底層結(jié)構(gòu): 和切片的結(jié)構(gòu)很像,只不過少了一個

    2024年02月14日
    瀏覽(98)
  • 【Go 基礎(chǔ)篇】Go語言字符類型:解析字符的本質(zhì)與應(yīng)用

    字符類型是計算機(jī)編程中用于表示文本和字符的數(shù)據(jù)類型,是構(gòu)建字符串的基本單位。在Go語言(Golang)中,字符類型具有獨(dú)特的特點(diǎn)和表示方式,包括Unicode編碼、字符字面值以及字符操作。本篇博客將深入探討Go語言中的字符類型,介紹字符的編碼方式、字符字面值的表示

    2024年02月13日
    瀏覽(22)
  • go語言將cmd stdout和stderr作為字符串返回而不是打印到控制臺

    從 golang 應(yīng)用程序中執(zhí)行 bash 命令,現(xiàn)在 stdout 和 stderr 直接進(jìn)入控制臺: 如果 bash 命令太慢( killInMilliSeconds 參數(shù)),程序應(yīng)該保持其終止 bash 命令的能力。 希望 stdout 和 stderr 作為字符串變量從 runBashCommandAndKillIfTooSlow 函數(shù)返回,而不立即打印到控 制臺,如何實(shí)現(xiàn)。 將輸出設(shè)

    2024年01月23日
    瀏覽(25)
  • go字符串詳解

    go字符串結(jié)構(gòu)體包含:指向底層存儲數(shù)組的指針、字符串長度。字符串按utf-8將字符編碼成二進(jìn)制數(shù),然后存儲在byte數(shù)組中。因?yàn)閡tf-8編碼一個字符可能占用多個字節(jié),例如一個漢字占3個字節(jié),所以字符串中的一個字符可能對應(yīng)byte數(shù)組中的多個元素。為了讓一個字符對應(yīng)數(shù)組

    2024年02月09日
    瀏覽(21)
  • Go字符串實(shí)戰(zhàn)操作大全!

    Go字符串實(shí)戰(zhàn)操作大全!

    在本篇文章中,我們深入探討了Go語言中字符串的魅力和深度。從基礎(chǔ)定義、操作、字符編碼到復(fù)雜的類型轉(zhuǎn)換,每個環(huán)節(jié)都帶有實(shí)例和代碼示例來深化理解。通過這些深入的解析,讀者不僅能夠掌握字符串在Go中的核心概念,還能洞察Go設(shè)計哲學(xué)背后的思考。 關(guān)注公眾號【

    2024年02月08日
    瀏覽(20)
  • go字符串去除首尾所有換行符

    原創(chuàng)不易,如果對你有幫助,歡迎給作者點(diǎn)個贊哦! 一鍵開啟舒適、快捷: 調(diào)用: 效果:

    2024年02月13日
    瀏覽(23)
  • 一個退役中校教你如何用go語言寫一個基于B+樹的json數(shù)據(jù)庫(進(jìn)階篇)之json字符串解析為BsTr結(jié)構(gòu)(一)

    1.對象式j(luò)son字符串 s := \\\"{\\\"put\\\":{\\\"putjsontest\\\":{\\\"aaa\\\":\\\"sdftsdfs\\\\dfe29asdf\\\",\\\"aaab\\\":true,\\\"arrarrstrct\\\":{\\\"nnn\\\":-1234567890,\\\"ccc\\\":[[\\\"sdftsdfs\\\\dfe29asdf\\\",\\\"nmbndfvdfgfdg\\\"],[\\\"sdftsdfs\\\\dfe29asdf\\\",\\\"poiuiyyttt\\\"]]},\\\"ddd\\\":\\\"sdftsdfs\\\\dfe29asdf\\\",\\\"fff\\\":false,\\\"comboolarr\\\":[{\\\"boolarr0\\\":[true,false]},{\\\"boolarr1\\\":[true,false]}]}

    2024年02月21日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包